1. 每个线程只有一个looper,一个消息队列。MessageQueue是 Looper 的内部类,被 Looper 持有。MessageQueue是个单链表结构,便于增删。
2. 主线程会提供好looper对象,直接使用handler的无参构造即可;子线程中要自己准备looper对象,并开启消息循环;
子线程中推荐使用ThreadHandler,它继承自Thread,并准备好了Looper对象。使用handler的有参构造,传入HandlerThread准备的Looper对象。此时虽然主线程创建了Handler,但是处理消息是在子线程中的。因为looper对象在子线程中。3. 主线程和HandlerThread子线程都会提供好looper,主线程中创建handler对象时,直接使用无参构造即可。handlermessage方法运行在主线程中,和looper在同一个线程中
子线程中创建handler对象,要使用有参的构造,把HandlerThread的looper传入。handlermessage方法运行在子线程中
耗时任务,则用handerThread,会执行在子线程中4. 1个线程,可能有n个handle,多个线程会有N*N个handler。怎么找到自己的looper的?hander在创建对象时,会和当前线程的looper关联。looper也能看到mq。消息内有个msg.target方法关联了当前handler,也知道找哪个handler的handlermessage方法。
5. Android的主线程是ActivityThread。TreadLocal:同一个对象,不同线程可以有不同的副本。
1 Handler机制--线程间通信的方式
子线程调用Handler对象的sendMessge方法发送消息给MessageQueue,而和Handler对象绑定的Looper对象,会通过loop方法从MessageQueue中获取消息,交由Handler对象的handleMessge方法处理,进行更新UI等操作。Looper对象运行在主线程,和Looper对象绑定的Handler的handleMessge方法也运行在主线程,这样消息就从子线程来到了主线程,实现了线程间的通信。
2. 如何理解Looper和Handler的绑定关系
Handler对象在创建时,会绑定一个Looper对象。
Handler对象的handleMessage方法和该Looper对象运行在同一线程中。
Handler对象和它绑定的Looper对象不一定运行在同一线程中。
1)在当前线程中创建Handler时,会调用Looper.myLooper()方法,获取当前线程的Looper对象,并有mLooper保存。
public Handler() {
this(null, false);
}
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();//会调用当前线程的Looper。若是主线程,会默认创建Looper;若是子线程,要自己创建Looper,否则会报错。
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;
}
2)主线程中,创建Handler对象时调用Handler的无参构造即可,因为主线程会默认提供好Looper对象,主线程的入口是ActivityThread的main方法:
public static void main(String[] args) {//frameworks/base/core/java/android/app
......
//创建Looper和MessageQueue对象,用于处理主线程的消息
Looper.prepareMainLooper();
//创建ActivityThread对象
ActivityThread thread = new ActivityThread();
//建立Binder通道 (创建新线程)
thread.attach(false);
mAnrAppManager.setMessageLogger(Looper.myLooper());
//消息循环运行
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
3)子线程中,调用Handler的无参构造,此时也会给mLooper赋值,但自己并未创建Looper对象,Looper.myLooper()获取为空,紧接着就会抛出异常。
此时要自己手动创建Looper对象,并开启消息循环。
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();//创建Looper对象
mHandler = new Handler() {
public void handleMessage(Message msg) {
// 这里处理消息
}
};
Looper.loop();//开启无线循环
}
}
4) 子线程中,上述创建handle对象的方式过于繁琐,就提供了HandlerThread。HandlerThread继承自Thread,内部创建了Looper。此时创建的Handler对象,传入HandlerThread的Looper对象,且Looper对象运行在子线程中,则Handler的handlemessage方法和Looper对象一样,也运行在子线程中。
HandlerThread 的使用例子
public class MainActivity extends Activity {
private static final String TAG = "lyl123";
private HandlerThread handlerThread;//子线程
private Handler mWorkHandler;//子线程Handler
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建子线程handlerThread
handlerThread = new HandlerThread("work_thread");
//启动子线程:创建子线程的Looper对象
handlerThread.start();
//利用子线程的Looper对象,创建子线程的Handler,同时传入回调接口
mWorkHandler = new Handler(handlerThread.getLooper(), new MyCallBack());
Log.e(TAG, "mWorkHandler will send msg from main thread");
mWorkHandler.sendEmptyMessage(1);
}
//该callback运行于子线程
class MyCallBack implements Handler.Callback{
@Override
public boolean handleMessage(Message msg) {
Log.e(TAG, "MyCallBack's handleMessage is in " + Thread.currentThread().getName());
mUIHandler.sendEmptyMessage(msg.what);
return true;
}
}
private Handler mUIHandler = new Handler(){//主线程Handler
@Override
public void handleMessage(Message msg) {
Log.e(TAG, "mUIHandler's handleMessage is in " + Thread.currentThread().getName());
}
};
@Override
protected void onDestroy() {
//停止handlerThread
handlerThread.quit();
super.onDestroy();
}
}
结合源码 分析: 在创建HandlerThread对象后必须调用其start()方法才能进行其他操作,而调用start()方法后相当于启动了子线程,会执行HandlerThread的run()方法
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
run方法中执行了Looper.prepare()代码,这时子线程的Looper对象将被创建,当Looper对象被创建后将和当前线程HandlerThread绑定。这样我们才可以在创建Handler对象时,使用Looper对象,进而确保Handler对象中的handleMessage方法是在子线程执行的。
handlerThread.getLooper()获取Looper对象:
public Looper getLooper() {
if (!isAlive()) {
return null;
}
// If the thread has been started, wait until the looper has been created.
synchronized (this) {
while (isAlive() && mLooper == null) {
try {
wait();//等待被唤醒
} catch (InterruptedException e) {
}
}
}
return mLooper;
}
通过getLooper方法获取looper对象时,会先先判断当前线程是否启动了,如果线程已经启动,那么将会进入同步语句并判断Looper是否为null,为null则代表Looper对象还没有被赋值,也就是还没被创建,此时当前调用线程进入等待阶段,直到Looper对象被创建,并在启动子线程的run()方法内调用notifyAll()方法唤醒等待的主线程,最后才返回Looper对象。
之所以需要等待唤醒机制,是因为Looper的创建是在子线程HandlerThread中执行的,而调用getLooper方法则是在主线程进行的,这样我们就无法保障我们在调用getLooper方法时Looper已经被创建,到这里我们也就明白了在获取mLooper对象时会存在一个同步的问题,只有当线程创建成功并且Looper对象也创建成功之后才能获得mLooper的值,HandlerThread内部则通过等待唤醒机制解决了同步问题。
此时创建Handler对象,最终会调用
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
当MyCallBack的对象传给mCallBack后,会在mWorkHandler的dispatchMessage方法中,调用MyCallBack的handleMessage方法处理消息。此时,mWorkHandler内没有重写handleMessage方法,而使用CallBack接口的handleMessage方法来处理消息。
/**
* 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);
}
}
退出该Activity时,调用子线程HandleThread的quit方法
5) intentService继承自Service ,intentService内部使用HandlerThread开启了子线程,用于处理耗时任务,执行完毕后,会调用stopSelf方法停止服务。
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public IntentService(String name) {
super();
mName = name;
}
......
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
* You should not override this method for your IntentService. Instead,
* override {@link #onHandleIntent}, which the system calls when the IntentService
* receives a start request.
* @see android.app.Service#onStartCommand
*/
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
/**
* Unless you provide binding for your service, you don't need to implement this
* method, because the default implementation returns null.
* @see android.app.Service#onBind
*/
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
/**
* This method is invoked on the worker thread with a request to process.
* Only one Intent is processed at a time, but the processing happens on a
* worker thread that runs independently from other application logic.
* So, if this code takes a long time, it will hold up other requests to
* the same IntentService, but it will not hold up anything else.
* When all requests have been handled, the IntentService stops itself,
* so you should not call {@link #stopSelf}.
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
* This may be null if the service is being restarted after
* its process has gone away; see
* {@link android.app.Service#onStartCommand}
* for details.
*/
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
在onCreate方法中,调用了HandleThread的构造创建了子线程thread,用于执行耗时任务。获取到了该线程的Looper对象后,传入了ServiceHandler,ServiceHandler是继承自Handler,此时重写了handlerMessage方法。
与4)不同,此时创建Handler对象时调用了
public Handler(Looper looper) {
this(looper, null, false);
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
此时mCallback为null,最后处理消息的是自定义handler时重写的handlerMessage方法,此时handlerMessage方法调用了onHandleIntent方法,且onHandleIntent方法是一个抽象方法,当我们在使用IntentServcie时,要重写onHandleIntent方法,执行具体的耗时任务。
当创建HandlerThread对象时,使用到了mName成员,而mName是从IntentService的有参构造中传过来的,故,在使用IntentService时要使用其有参构造,传入子线程的名字。
6)AsyncTask的底层也是使用了Handler机制:AsyncTask源码分析