android Handler 机制梳理
来源:互联网 发布:网络客服流程图 编辑:程序博客网 时间:2024/06/06 01:45
最近对android Handler实现原理比较感兴趣,抽空分析了一下Handler java层实现原理,梳理如下
main loop 在哪里创建的?SystemServer run ActivityThread main
enqueueMessage逻辑?
类图:
1.loop.prepare 会检查当前线程是否存在loop 有则抛异常 否则创建loop实例 因此一个线程只能存在一个loop实例 该实例会创建一个messagequeue 故一个线程只有一个 messagequeue
2.loop.loop会让该实例所在线程进入死循环 不断从从messageQueue中获取消息调用msg.target.disparchMessage
3.创建handler时会获取所在线程的loop 并与loop的messageQueue关联
4.sendMssage 方法会将target设置handler自身并将message加入到messageQueue,同样post(Runnable)方法也一样
5.loop在接收到Message后获取其target然后调用dispatchMessage 派发消息调用handMessage
以下代码红色部分解释以上1、2、3、4、5步
- Looper prepare()
private static void prepare(boolean quitAllowed) {
//检查所在线程是否存在loop 如存在抛出异常,所以prepare在同一个线程里只可以调用一次,即同一个线程只可有一个loop if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); }
//否则创建loop sThreadLocal.set(new Looper(quitAllowed));}
private Looper(boolean quitAllowed) {
//looper创建消息队列 mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread();}
- Looper.java loop()
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process, // and keep track of what that identity token actually is. Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity(); //死循环 for (;;) {
//读取消息队列消息 Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } //派发消息 msg.target.dispatchMessage(msg); if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); } // Make sure that during the course of dispatching the // identity of the thread wasn't corrupted. final long newIdent = Binder.clearCallingIdentity(); if (ident != newIdent) { Log.wtf(TAG, "Thread identity changed from 0x" + Long.toHexString(ident) + " to 0x" + Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what); } msg.recycleUnchecked(); }}
- Handler myLooper()
public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } //获取looper实例 mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); }
//获取looper消息队列 mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
4.Handler sendMessage
/** * Return the Looper object associated with the current thread. Returns * null if the calling thread is not associated with a Looper. */public static @Nullable Looper myLooper() { return sThreadLocal.get();}
public final boolean sendMessage(Message msg){ return sendMessageDelayed(msg, 0);}
public final boolean sendMessageDelayed(Message msg, long delayMillis){ if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);}
////////美丽的///////分隔线///////////////////////////////
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis);}
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//将target设置为自己 即loop dispatchMessage方法中被调用
//msg.target.dispatchMessage(msg); msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}
//post 方法是生成了一个带Callback的Message
//调用msg的target target是发送Message的Handler
msg.target.dispatchMessage(msg);
/** * Handle system messages here. */public void dispatchMessage(Message msg) {
//优先处理回调再处理handleMessage if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); }}
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m;}
5.Looper loop()
消息的回收利用机制,是维护了一个池,这个池以链表方式存储 当获取消息时从链头取出,若消息池中没有可复用则创建新消息,当回收(把消息池中添加)消息时将新回收消息添加至链头
回收消息代码片段:
/** * Recycles a Message that may be in-use. * Used internally by the MessageQueue and Looper when disposing of queued Messages. */void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } }}
获取消息代码片段:
AsyncQueryHandler.WorkerHandler也继承自Handler 非UI线程操作处理类 在该类执行增删改操作
HandlerThread 独立线程的Loop管理类
工作流程如下:
1.创建AsyncQueryHandler实例会同时创建工作线程Handler
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message();}
池最大为50条消息,即链表长度最多可回收50条消息
private static final int MAX_POOL_SIZE = 50;
////////////////////分隔线/////////////////////
后来我又发现了AsyncQueryHandler 什么鬼?
查看源码发现AsyncQueryHandler主要做了一个异步操作数据(ContextProvider)的架构.
AsyncQueryHandler继承自Handler handMessage处理是否在自线程与Handler一样取决于构造该对象时所在线程
public AsyncQueryHandler(ContentResolver cr) { super();
//弱引用Resolver对象 mResolver = new WeakReference<ContentResolver>(cr); synchronized (AsyncQueryHandler.class) { if (sLooper == null) {
//HandlerThread负责创建一个线程并生成loop HandlerThread thread = new HandlerThread("AsyncQueryWorker"); thread.start(); sLooper = thread.getLooper(); } }
//获取HandlerThread生成的loop 因为在自线程所以mWorkeThreadHandler工作在自线程 mWorkerThreadHandler = createHandler(sLooper);}
2.HandlerThread 启动线程并创建loop HandlerThread是继承Thread的
@Overridepublic void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1;}
3.发生查询或者其他插入操作请求到工作线程
public final void startInsert(int token, Object cookie, Uri uri, ContentValues initialValues) { // Use the token as what so cancelOperations works properly Message msg = mWorkerThreadHandler.obtainMessage(token); msg.arg1 = EVENT_ARG_INSERT; WorkerArgs args = new WorkerArgs();
//处理者设置为自己 args.handler = this; args.uri = uri; args.cookie = cookie; args.values = initialValues; msg.obj = args; //发消息到工作线程 mWorkerThreadHandler.sendMessage(msg);}
4.工作线程处理操作请求并将处理结果返回给AsyncQueryHandler(一般为UI线程中)
if (resolver == null) return; WorkerArgs args = (WorkerArgs) msg.obj; int token = msg.what; int event = msg.arg1; switch (event) { case EVENT_ARG_QUERY: cursor = resolver.query(args.uri, args.projection, args.selection, args.selectionArgs, args.orderBy); args.result = cursor; break;
Message reply = args.handler.obtainMessage(token); reply.obj = args; reply.arg1 = msg.arg1;
reply.sendToTarget();
//将结果发消息回AsyncQueryHandler
protected class WorkerHandler extends Handler { public WorkerHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) {
//获取弱引用对象 这样AsyncQueryHandler被销毁后 不会一直引用着防止内存泄漏 final ContentResolver resolver = mResolver.get();
1 0
- android Handler 机制梳理
- Android杂谈(25)Handler机制梳理
- Android理论梳理-No1异步处理之Handler相关机制
- Android Handler 梳理
- handler机制 源码分析 梳理
- Android Handler 梳理(二)
- Handler机制流程梳理、源码分析
- Android消息机制梳理
- 【Android】从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- 从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
- Android HandlerThread、Looper、Handler 知识点梳理
- CentOS 7 上安装 Redis3.2.3 并开启外网访问(亲测好用,转)
- 程序的版式
- Trailing Zeroes (III) LightOJ
- 安卓学习笔记---Android通知栏微技巧,通知栏图标在sdk21以上及以下的区别
- 银行家算法简述解析
- android Handler 机制梳理
- UVA 1584
- 生产环境下CPU过高故障排查--top、ps、grep、printf、jstack等命令排查
- 消除Connect Devices中无用的设备信息
- iOS 对于上架项目崩溃日志解析
- RSA实现JS前端加密,PHP后端解密
- JSON时间对象序列化与反序列化<Timestamp>
- oracle 图形化界面工具的安装
- 区分性训练