我们通常在Activity中创建的Handler,是与UI线程绑定的,这里说的绑定其实是指,Looper和MessageQueue的绑定,
而这里的线程,也就是Looper和MessageQueue所在的线程,也就是说Handler所持有的Looper和MessageQueue是
哪个线程的,我们就说,此Handler是与哪个线程绑定的。
下面先看一个例子
package com.example.liaoli.handler_demo; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; public class MainActivity extends AppCompatActivity { private static final String TAG = "Handler_demo"; private Handler UIHandler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e(TAG, "UI线程:" + Thread.currentThread()); } }; class MyThread extends Thread { public Handler handler ; public Looper looper; public void run(){ Looper.prepare(); looper = Looper.myLooper(); handler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e(TAG,"当前线程:" + Thread.currentThread()); } }; Looper.loop(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyThread mt = new MyThread(); mt.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } mt.handler.sendEmptyMessage(0); UIHandler.sendEmptyMessage(0); } }
运行之后打印的结果是:
09-26 18:10:32.072 30495-30507/com.example.liaoli.handler_demo E/Handler_demo﹕ 当前线程:Thread[Thread-170,5,main]
09-26 18:10:32.080 30495-30495/com.example.liaoli.handler_demo E/Handler_demo﹕ UI线程:Thread[main,5,main]
以上结果说明
@Override public void handleMessage(Message msg) { Log.e(TAG,"当前线程:" + Thread.currentThread()); }中的代码是运行在子线程中的,此时我们其实就是创建了一个与子线程绑定的Handler实例。
子线程的run方法中的
looper = Looper.myLooper();
其实就是在创建一个本子线程的Looper 实例,而在创建Looper的时候又会创建MessageQueue,
然后在handler的构造方法中会拿到这两个实例,从而建立绑定关系。看Handler源码
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()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async; }
再看Looper的myLooper()方法
/** * 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(); }
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
sThreadLocal
是ThreadLocal类的一个实例,Threadlocal类的作用就是,来实现线程的数据共享与分离,
这里的共享指的是同一个线程间的共享,分离指的是不同线程件的分离,我们可以将其理解
成一个Map,这个Map的key是我们的线程实例,value就是我们存的与此线程相关的值,当然
ThreadLocal存取并不需要指定Key,只需要用
public T get()和
public void set(T value)方法来取和存数据,当然必须得先存了在能取到数据。
ThreadLocal会根据线程去取或存这个值。也就是说只有同一个线程中取出来的值才是同一个值,
其实,简单理解成Map就好。
这也就能解释为什么我们在通常我们在Activity中创建用来更新UI的界面为什么会运行在UI线程中的问题。
这就是因为为我们创建的Handler是与ActivityThread的UI线程中Looper绑定的
ActivityThread的main方法中的代码片段:
Looper.prepareMainLooper();
……
……
Looper.loop();
这就在主(UI)线程中,创建了一个Looper,然后我们在Activity(UI线程中)中创建了一个Handler,Handler 在构造函数中
就会和这个主线程中的Looper绑定。所以此时Handler的
private Handler UIHandler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e(TAG, "UI线程:" + Thread.currentThread()); } };
的
public void handleMessage(Message msg)
中的代码是运行在UI线程中的。
再看
public class MainActivity extends AppCompatActivity { private static final String TAG = "Handler_demo"; private Handler myHandler; class MyThread extends Thread { public Handler handler ; public Looper looper; public void run(){ Looper.prepare(); looper = Looper.myLooper(); handler = new Handler(){ @Override public void handleMessage(Message msg) { Log.e(TAG,"当前线程:" + Thread.currentThread()); } }; Looper.loop(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MyThread mt = new MyThread(); mt.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } mt.handler.sendEmptyMessage(0); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } myHandler = new Handler(mt.looper){ @Override public void handleMessage(Message msg) { Log.e(TAG, "Run IN 线程:" + Thread.currentThread()); } }; myHandler.sendEmptyMessage(0); } }
运行结果
09-26 18:18:44.784 1931-1943/com.example.liaoli.handler_demo E/Handler_demo﹕ 当前线程:Thread[Thread-176,5,main]
09-26 18:18:46.784 1931-1943/com.example.liaoli.handler_demo E/Handler_demo﹕ Run IN 线程:Thread[Thread-176,5,main]
发型这两个Handler的Handler的
public void handleMessage(Message msg)方法的代码是运行在同一个线程的,
也就是说 Looper是哪个线程的,与之绑定的Handler的
public void handleMessage(Message msg)方法就运行与哪个线程。