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

从HandlerThread 的使用来分析HandlerThread的源码

2016-07-06 16:05 741 查看
转载请注明出处:

http://blog.csdn.net/yianemail/article/details/51839509

一:前言

再分析HandlerThread 的使用之前,我们先来简要介绍一下在android中线程的几种表现形式。

线程在android 中是很重要的概念,由于android的uiThread特性,我们常常要利用子线程进行耗时操作。uiThread进行界面的更新处理。在android 中,出了最为常见的Thread之外,还有AsyncTask,IntentService 以及要介绍的HandlerThread。

上述几种虽然都是android 中概念意义上的线程,但是它们具有不同的特性以及不同的使用场景。

AsyncTask 我们在前文已经介绍,底层封装了线程池以及利用Handler更新ui

IntentService内部则使用了HandlerThread

HandlerThread 则是Thread以及looper的封装

二:HandlerThread实例

为了表现HandlerThread 与传统的使用new thread () 的使用区别,我们分别写两个demo来加以区分。

1,通过使用new thread () 形式更新ui

看下activity代码

public class NewThreadUiActivity extends AppCompatActivity {
private static final int MESSAGE_UI_HANDLER = 0X11;
private static final int MESSAGE_THREAD_HANDLER = 0X12;
private Looper threadLooper;
private TextView textView;
/**
* 此handler 是UI线程的Handler
*/
Handler uiHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_UI_HANDLER:
textView.setText("执行更新");
break;
}
}
};

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.messgae_tv);
/**
* 子线程模拟耗时任务
*/
new ThreadLooper().start();
}

class ThreadLooper extends Thread {
@Override
public void run() {
super.run();
Looper.prepare();
threadLooper = Looper.myLooper();
/**
* 子线程的Handler
*/
Handler threadHandler = new Handler(threadLooper) {
@Override
public void handleMessage(Message message) {
super.handleMessage(message);

switch (message.what) {

case MESSAGE_THREAD_HANDLER:
uiHandler.sendEmptyMessageDelayed(MESSAGE_UI_HANDLER, 1000);
break;
}
}
};

threadHandler.sendEmptyMessageDelayed(MESSAGE_THREAD_HANDLER, 1000);

Looper.loop();
}
}
}


主界面很简单,就只有一个textview,我们在onCreat()中通过执行匿名线程 。执行逻辑可能有点绕,我们看到在程序中我们实例化了uiHandler 以及threadHandler 两个handler ,其中uiHandler 用来更新界面,threadHandler 用来作为一个过渡,往uiHandler发送messgae 用来提醒uiHandler 更新界面。

你可能要问了,

“wtf ?! , 明明一个handler 就可以,你为毛弄两个?“

咳咳,这位大哥,你忘了我们本文要介绍的主题了么,HandlerThread是封装了thread 以及looper ,(注意该looper 是子线程的looper)。既然有looper 我们自然开启looper.loop() ;这样才能为后来的HandlerThread 的使用做出来更加鲜明的对比。

看下执行结果,



2,通过使用Handlerthread 形式更新ui

public class NewThreadUiActivity extends AppCompatActivity {
private static final int MESSAGE_UI_HANDLER = 0X11;
private static final int MESSAGE_THREAD_HANDLER = 0X12;
private Looper threadLooper;
private TextView textView;
/**
* 此handler 是UI线程的Handler
*/
Handler uiHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case MESSAGE_UI_HANDLER:
textView.setText("执行更新");
break;
}
}
};

@Override
protected void onDestroy() {
super.onDestroy();
//别忘了在onDestroy 退出

handlerThread.quit();
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.messgae_tv);

HandlerThread handlerThread=new HandlerThread("handlerthread");
handlerThread.start();

Handler threadHandler=new Handler(handlerThread.getLooper());
uiHandler.sendEmptyMessageDelayed(MESSAGE_UI_HANDLER, 1000);

}

}


可以看到,采用HandlerThread 的方式为我们省去了new Thread() 以及looper.prepare()等一些列方法。获得了跟new Thread()的方式相同的效果。

三:HandlerThread源码分析

首先看HandlerThread 的实现方式

HandlerThread handlerThread = new HandlerThread("handlerthread");

handlerThread.start();


看下构造函数

/**
* Handy class for starting a new thread that has a looper. The looper can then be
* used to create handler classes. Note that start() must still be called.
*/
...

public HandlerThread(String name) {
super(name);
mPriority = Process.THREAD_PRIORITY_DEFAULT;
}


其实看下它的注释就能明白大概意思,“开启一个带有looper的新的线程….请注意一定要调用start() 方法“

在构造函数中,设置了一下他的默认优先级

通过源码我们可知,HandlerThread 是Thread的子类,

再来分析一下start() 方法,(也就是run)

@Override
public void run() {
//获得当前线程的id
mTid = Process.myTid();
//实例化message QUEUE等,
Looper.prepare();
//持有锁机制来获得当前线程的Looper对象
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
//该方法实现体是空的,子类可以实现该方法,作用就是在线程循环之前做一些准备工作,
onLooperPrepared();
//启动loop 循环
Looper.loop();
mTid = -1;
}


以上代码中的注释已经写得很清楚了,以上run方法主要作用就是调用了Looper.prepare和Looper.loop构建了一个循环线程。

其实本质还是handler 的一套机制。

四:总结:

1.HandlerThread适用于构建循环线程。

2.在创建Handler作为HandlerThread线程消息执行者的时候必须调用start方法之后,因为创建Handler需要的Looper参数是从HandlerThread类中获得,而Looper对象的赋值又是在HandlerThread的run方法中创建。

源码下载:https://github.com/outparadox/HandlerThread
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息