从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
更多相关文章
- Android中Intent的使用示例
- android中DexClassLoader类的使用
- Android(安卓)4.0 更新后 启动不了.
- Android(安卓)Kotlin开发之Hello World
- Android(安卓)Handler
- android中AVD的使用
- 箭头函数的基础使用
- NPM 和webpack 的基础使用
- Python list sort方法的具体使用