您的位置:首页 > 移动开发 > Android开发

《android系统源代码情景分析》学习-第15章 Android应用线程的消息循环模型

2018-02-08 17:50 375 查看

1 三种消息循环模型

1.1 主线程消息循环

第12章最后,AMS请求Zygote创建应用程序进程后,会自动进入主线程的消息循环,也就是ActivityThread。

//创建一个主线程消息循环
Looper.prepareMainLooper();
//创建一个ActivityThread实例
ActivityThread thread = new ActivityThread();
thread.attach(false);
//当前主线程进入到消息循环
Looper.loop();


Looper.prepareMainLooper()方法只能在主线程中调用,而且只能被调用一次。所以我们写代码时不能调用这个方法,否则会出异常。这个方法会生成一个Looper对象mMainLoopeer,在其他的子线程中就可以通过 Looper.getMainLooper()获取mMainLopper,完成与主线程的界面更新。

1.2 与UI无关的子线程消息循环模型

子线程有两类,一种是不具有消息循环的子线程,这种是我们经常见到的Thread,一般不直接使用new Thread的方式来创建一个子线程,而是自定义一个Thread实现类,然后用这个实现类创建子线程,在重写的run()中实现业务逻辑。

这种子线程没有消息循环,run方法执行完毕线程就会结束。

另一种是具有消息循环的子线程,也就是与UI无关的子线程消息循环模型。

我们使用HandlerThread创建一个具有消息循环的子线程。HandlerThread继承自Thread.

1.2.2 消息循环的创建

public class HandlerThread extends Thread{
private Looper mLooper;
public HandlerThread(String name){
super(name);
}
public void run(){
Looper.prepare();
synchronized(this){
mLooper = Looper.myLooper();
}
Looper.loop();
}
public Looper getLopper(){
return mLooper;
}

public boolean quit(){
Looper looper = getLooper();
if(looper!=null){
looper.quit();
return true;
}
return false;
}
}


可以看到, run方法里面首先调用Looper.prepare()创建了一个消息循环,然后Looper.loop()使得当前线程进入消息循环。所以HandlerThread就有了消息循环。

1.2.2 HandlerThread的使用

首先创建一个HandlerThread

HandlerThread handlerThread = new HandlerThread("handler thread");
handlerThread.start();


定义一个实现了Runnable的类ThreadTask

public class ThreadTask implements Runnable{
public ThreadTask(){
}
public void run(){
}
}


新建一个ThreadTask实例

ThreadTask threadTask = new ThreadTask();

将threadTask封装成一个消息发送到消息队列

Handler handler = new Handler(handlerThread.getLooper());
handler.post(threadTask);


消息被处理时就会调用threadTask的run方法,执行自定义任务。

如果一直不往子线程消息队列发送消息,那么子线程就会进入睡眠等待状态。

退出子线程时,只需要

handlerThread.quit();


调用了looper.quit();

Message msg =Message.obtain();
mQueue.enqueueMessage(msg,0);


通过向线程的消息队列发送一个target为null的Message对象,线程就会退出消息循环,停止线程 。

1.3 与UI有关的子线程消息循环模型 AsyncTask

AysncTask的三个主要方法:doInBackground(),onProgressUpdate(),onPostExecute();

其中doInBackground()执行耗时操作,是在子线程运行,onProgressUpdate(),onPostExecute()都可以操作界面,是在主线程运行。

frameworks/base/core/java/android/os/AsyncTask.java

public abstract class AsyncTask<Params,Progress,Result>{}


未完,待续
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: