Android Handler分析
--源码注释
简单说,handler就是Android类库提供的用于传递、接收和处理Message和Runnable对象的一个处理类,同时handler与线程的MessageQueue消息队列关联在一起。每个handler实例斗鱼一个单独的线程及该线程的消息队列相关联。
1.异步消息处理机制
. Message : 消息体,用于装载需要发送的对象 (Defines a message containing a description and arbitrary data object that can be sent to a {@link Handler}.)
. Looper : 用于为线程运行消息循环的类 (Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one,call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.)
. MessageQueue : 消息队列,持有一批消息体,以待looper进行分发。 (Low-level class holding the list of messages to be dispatched by a{@link Looper}. Messages are notadded directly to a MessageQueue, but rather through {@link Handler} objects associated with the Looper.)
. Handler : handler就是Android类库提供的用于传递、接收和处理Message和Runnable对象的一个处理类
首先,要理清它们之间的内在联系。Handler和Looper对象是属于线程内部的数据,不过也提供与外部线程的访问接口,Handler就是公开给外部线程的接口,用于线程间的通信。Looper是由系统支持的用于创建和管理MessageQueue的依附于一个线程的循环处理对象,而Handler是用于操作线程内部的消息队列的,所以Handler也必须依附一个线程,而且只能是一个线程。
异步消息处理流程的简单梳理:
当应用程序开启时,系统会自动为UI线程创建一个MessageQueue(消息队列)和Looper循环处理对象。首先需要在主线程中创建一个Handler对象,并重写handlerMessage()方法。然后当子线程中需要进行UI操作时,就创建一个Message对象,并通过Handler将这条消息发送出去。之后这条消息就会被添加到MessageQueue的队列中等待被处理,而Looper则会一直尝试从MessageQueue中取出待处理消息,并找到与消息对象对应的Handler对象,然后调用Handler的handleMessage()方法。由于Handler是在主线程中创建的,所以此时handleMessage()方法中的代码也会在主线程中运行,于是我们在这里就可以安心地进行UI操作了。
在实际开发中,我们习惯用handler将在子线程中计算运行得到的数据结果包装成message对象,然后通过handler发送给主线程(UI线程)中。
2. Handler Demo Code
public class MainActivity extends AppCompatActivity { private MHandler mHandler = new MHandler(); private int a = 0; private TextView tv_theme; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); Log.i("jon", "线程: " + Thread.currentThread().getName()); Log.i("jon", "a : " + a); // startRunnable(); startThread(); } //初始化视图组件 private void initView(){ tv_theme = (TextView) findViewById(R.id.tv_theme); } //在主线程调用handler的post方法,运行run方法内的代码 private void startRunnable() { //handler的post方法貌似是开启了一个子线程,而实际上仍然是运行在主线程之上的 //post方法实际上是生成一个Message对象,并将runnable对象的值赋给Message对象的callback属性, //再将Message对象放置到消息队列当中 mHandler.post(new Runnable() { @Override public void run() { a++; Log.i("jon", "线程: " + Thread.currentThread().getName()); Log.i("jon", "a: " + a); } }); } //开启子线程 private void startThread() { Thread thread = new Thread(new Runnable() { @Override public void run() { a++; Log.i("jon", "线程: " + Thread.currentThread().getName()); Log.i("jon", "a: " + a); String str = "国王驾到!!!"; Message msg = mHandler.obtainMessage(); msg.obj = str; mHandler.sendMessage(msg); //进入主线程 } }); thread.setName("子线程1"); thread.start(); } /** * handler的子类,重写handlerMessage方法 */ class MHandler extends Handler { //进入主线程 @Override public void handleMessage(Message msg) { Log.i("jon", "handler此时所在的线程: " + Thread.currentThread().getName()); String str = (String) msg.obj; if(null != str){ Log.i("jon", "handler接收到的消息是: " + str); tv_theme.setText(str); } } } }
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.buaa.concurrencydemo.MainActivity"> <TextView android:id="@+id/tv_theme" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/> </android.support.constraint.ConstraintLayout>
3.Handler的Post方法源码分析
Handler:
public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r), 0); }
private static Message getPostMessage(Runnable r) { Message m = Message.obtain(); m.callback = r; return m; }
Message:
/*package*/ Runnable callback;
/** * 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(); }
看到这里就知道,handler的post方法只是把runnable对象赋给了Message的成员变量callback,
而callback也是一个Runnable类型的对象
Looper:
try { msg.target.dispatchMessage(msg); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logging != null) { logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); }
这里msg是一个Message类型的对象实例
Message:
/*package*/ Handler target
msg.target其实就是一个Handler类型的对象实例, msg.target.dispatchMessage(msg)方法其实质就是调用了handler的dispatchMessage方法,
Handler:
/** * 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); } }
private static void handleCallback(Message message) { message.callback.run(); }
从handlerCallback方法我可以看到,这里只是调用了Runnable对象实例的run方法,而从java基础知识的角度出发,
直接调用run方法并不会开启新的线程,所以此时代码仍然在主线程上运行。因此handler的post(Runnable runnable)方法
并不会开启新的子线程。