从HandlerThread 的使用来分析HandlerThread的源码
Posted yian_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从HandlerThread 的使用来分析HandlerThread的源码相关的知识,希望对你有一定的参考价值。
转载请注明出处:
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
以上是关于从HandlerThread 的使用来分析HandlerThread的源码的主要内容,如果未能解决你的问题,请参考以下文章