Handler+Message+MessageQuque+Looper 异步加载类 消息处理机制 分析
16lz
2021-01-24
其实在平时开发、面试、技术交流都会提到Android消息处理机制,记得有次去面试有问道,消息处理流程,我相信这个对于开发Android两年都很简单,但是具体问道每个类作用和具体回调机制,每个对象分布在那个线程里,这时候就有点不清楚了,我回来之后就详细研究了Handler、Message、MessageQueue、Looper,ActivityThread,总结如下:
一.对象描述
1.应用程序启动在attach方法中加载ActivityThread线程管理类,在main()中调用looper循环读取消息队列.
2.Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列),消息处理机制核心功能就在Looper里面处理,Looper通过next操作先从MessageQueue取消息,然后通过disptchMessage方法通知Handler回传给
3.Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里,或者接收Looper(从Message Queue取出)所送来的消息。
4.Message Queue(消息队列),用于管理消息队列,在Handler初始化的时候会创建一个Message Queue 对象和Looper对象。
二.应用启动一个Looper循环读取消息队列流程如下:
//在Activity中attach流程时,传入ActivityThread线程对象
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config)
//在ActivityThread main中启动设置looper对象,并启动循环操作
public static void main(String[] args) { /// M: Retrieve the information from AMS @{ if ( args != null && args.length > 0 ) { if ( args[0].equals("enable") ) { mEnableAppLaunchLog = true; } if ( args[1].equals("true") ) { mIsUserBuild = true; } if ( args[2].equals("true") ) { mBooted = true; } } /// @} logAppLaunchTime(TAG, "ActivityThread is created"); /// M: It's for debugging App Launch time SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); if (sMainThreadHandler == null) { sMainThreadHandler = new Handler(); } ActivityThread thread = new ActivityThread(); thread.attach(false); AsyncTask.init(); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } /// M: ALPS00270724 message history mechanism @{ if (!"user".equals(android.os.Build.TYPE)) { Looper.myLooper().setMessageLogging(new MessageLogger()); } /// @}//执行looper循环消息循环操作 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
三.讲向消息队列加入消息详细流程分析如下:
下面我们先从Handler讲起,Handler是异步加载类,先从Handler初始化函数分析。
import android.util.Log;import android.util.Printer;import java.lang.reflect.Modifier;public class Handler { /* * Set this flag to true to detect anonymous, local or member classes * that extend this Handler class and that are not static. These kind * of classes can potentially create leaks. */ private static final boolean FIND_POTENTIAL_LEAKS = false; private static final String TAG = "Handler"; final MessageQueue mQueue; final Looper mLooper; final Callback mCallback; IMessenger mMessenger; /** * Callback interface you can use when instantiating a Handler to avoid * having to implement your own subclass of Handler. */ public interface Callback { public boolean handleMessage(Message msg); } /** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { } /** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } } /** * *初始化Handler对象 * */ public Handler() { //Java反射机制来验证是不是Handler对象 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对象,Looper.myLooper就是返回一个同步线程类 mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } //初始化MessageQueue mQueue = mLooper.mQueue; mCallback = null; } /** * Constructor associates this handler with the queue for the * current thread and takes a callback interface in which you can handle * messages. */ public Handler(Callback callback) { } /** * 由外部设置looper * */ public Handler(Looper looper) { } /** * 由外部设置looper,和回调对象。 * */ public Handler(Looper looper, Callback callback) { } /** * * sendMessageAtTime是最终加入消息队列的方法,在设置时间戳后加入消息对象中,以时间戳为队列 * uptimeMillis参数是时间戳, * Message 是消息对象, * * */ public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { //这个很关键,这个是指定消息回调对象, msg.target = this; sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } /** * Enqueue a message at the front of the message queue, to be processed on * the next iteration of the message loop. You will receive it in * {@link #handleMessage}, in the thread attached to this handler. * <b>This method is only for use in very special circumstances -- it * can easily starve the message queue, cause ordering problems, or have * other unexpected side-effects.</b> * * @return Returns true if the message was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean sendMessageAtFrontOfQueue(Message msg) { boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; sent = queue.enqueueMessage(msg, 0); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } /** * 从一个消息队列中删除一个消息 * */ public final void removeMessages(int what) { mQueue.removeMessages(this, what, null); } final IMessenger getIMessenger() { synchronized (mQueue) { if (mMessenger != null) { return mMessenger; } mMessenger = new MessengerImpl(); return mMessenger; } } private final class MessengerImpl extends IMessenger.Stub { public void send(Message msg) { Handler.this.sendMessage(msg); } } private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; } private static Message getPostMessage(Runnable r, Object token) { Message m = Message.obtain(); m.obj = token; m.callback = r; return m; } private static void handleCallback(Message message) { message.callback.run(); } }
四.讲Looper线程队列管理流程详解:
//Looper类分析public class Looper { //static变量,判断是否打印调试信息。 private static final boolean DEBUG = false; private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; // sThreadLocal.get() will return null unless you've called prepare().//线程本地存储功能的封装,TLS,thread local storage,什么意思呢?因为存储要么在栈上,例如函数内定义的内部变量。要么在堆上,例如new或者malloc出来的东西//但是现在的系统比如Linux和windows都提供了线程本地存储空间,也就是这个存储空间是和线程相关的,一个线程内有一个内部存储空间,这样的话我把线程相关的东西就存储到//这个线程的TLS中,就不用放在堆上而进行同步操作了。 private static final ThreadLocal sThreadLocal = new ThreadLocal();//消息队列,MessageQueue,看名字就知道是个queue.. final MessageQueue mQueue; /** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */ //这个loop是在ActivityThread对象中main启动时调用loop方法 //这个是static函数喔!
public static final void loop() { Looper me = myLooper();//从该线程中取出对应的looper对象 MessageQueue queue = me.mQueue;//取消息队列对象... while (true) { Message msg = queue.next(); // might block取消息队列中的一个待处理消息.. //if (!me.mRun) {//是否需要退出?mRun是个volatile变量,跨线程同步的,应该是有地方设置它。 // break; //} if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); } } }}
更多相关文章
- [置顶] Android基于XMPP Smack Openfire开发IM(5)发送消息
- Android中桌面图标显示通知消息的数量
- Asynchronous HTTP Requests in Android(安卓)Using Volley
- Android学习笔记(38):Handler消息传递处理机制
- Android中的Handler:接受子线程发送的数据, 并用此数据配合主线
- Android:异步处理之Handler、Looper、MessageQueue之间的恩怨(三)
- Android(安卓)之 Choreographer 详细分析
- 【Android】实现登录、注册、数据库操作(极复杂)
- android中的ANR