Android多线程(三)HandlerThread源码原理解析
HandlerThread实例
在上一遍中文章Android消息处理机制—Handler、Message、Looper源码原理解析中我们学习了Looper、Handler、Message之间的关系,在子线程中创建Handler的过程稍显复杂,有没有一种更简单的办法呢,答案是肯定的,其实Android已经为我们封装了一个Handler、Looper的结合体——HandlerThread,我们来看一个HandlerThread的实例:
public class MainActivity extends Activity { private HandlerThread mHandlerThread; //工作在子线程中的Handler private Handler mSecondHandler; //工作在UI线程中的Handler private Handler mUIHandler; private int MESSAGE_WORK = 0X01; private int MESSAGE_DONE = 0X02; private Button mButton; private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = (Button) findViewById(R.id.send); mTextView = (TextView) findViewById(R.id.tx); mUIHandler = new Handler(){ @Override public void handleMessage(Message msg) { //UI线程中的Handler收到后信息更新界面 super.handleMessage(msg); if (msg.what == MESSAGE_DONE) { mTextView.setText("the number is : " + msg.arg1); } } }; mHandlerThread = new HandlerThread("test"); //必须调用 mHandlerThread.start(); mSecondHandler = new Handler(mHandlerThread.getLooper()){ @Override public void handleMessage(Message msg) { //工作在子线程中 super.handleMessage(msg); try { //模拟耗时操作 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally { //耗时操作完成后通过UIHandler通知UI线程更新界面 Message done = new Message(); done.what = MESSAGE_DONE; Random rand = new Random(); done.arg1 = rand.nextInt(100); mUIHandler.sendMessage(done); } } }; //发送消息给子线程中的Handler mSecondHandler.sendEmptyMessage(0x123); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mSecondHandler.sendEmptyMessage(MESSAGE_WORK); } }); } @Override protected void onDestroy() { super.onDestroy(); //不再使用时释放Looper mHandlerThread.quit(); }}
在上面的例子中,我们在子线程中使用创建Handler来处理消息时只需创建一个HandlerThread,并在创建子线程Handler的时候传入HandlerThread.getLooper() ,不再需要调用Looper.prepare()和Looper.loop(),甚至不用创建Thread,看上去是不是简单多了,接下来看看Handlerthread是怎样工作的。
源码分析
其实HandlerThread的源码只有200行不到:
public class HandlerThread extends Thread { int mPriority; int mTid = -1; Looper mLooper; public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } public HandlerThread(String name, int priority) { super(name); mPriority = priority; } protected void onLooperPrepared() { } @Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; } 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; }}
从以上源码中可以知道,其实HandlerThread其实是一个Thread,我们通过它的构造函数指定HandlerThread的名字,设置线程的优先级,默认情况的线程级别是0。既然是继承Thread类,那最重要的肯定是重写run()方法了,在HandlerThread的run()中首先通过Looper.prepare()来获取创建Looper实例,所以我们要在创建Handler之前要调用start()方法,然后回调run()去创建Looper对象,在run()方法中通过线程同步去给当前成员变量mLooper赋值,当mLooper = Looper.myLooper()完成之后,通过notifyAll()通知mLooper已经创建完成,然后getLooper()时才能获取到Looper对象,否则getLooper()这个方法就会一直wait(),直到Looper被初始化。此外,我们可以通过重写onLooperPrepared()这个方法在Looper.looper()开始前执行我们需要的一些操作,然后run()中调用Looper.loop(),这样Looper就开始工作了。
通过以上的分析可知,原来HandlerThread已经为我们创建好了Looper对象,我们只需要在创建Handler时通过getLooper()方法将Looper实例传入即可,这样一套完整的消息处理机制就完成了,当我们不在需要HandlerThread时记得通过下面两个方法Looper循环:
public boolean quit() { Looper looper = getLooper(); if (looper != null) { looper.quit(); return true; } return false;}public boolean quitSafely() { Looper looper = getLooper(); if (looper != null) { looper.quitSafely(); return true; } return false;}
这两个方法的不同点在于,quitSafely()会在清空消息之前继续派发所有非延迟消息,而quit()则会立即清空所有的非延迟消息和延迟消息(通过sendMessageDelayed或通过postDelayed等方法发送的为延迟消息)。
更多相关文章
- Android(安卓)Studio真机测试时生成的程序出现闪退
- Android网络请求框架AsyncHttpClient (android-async-http)介绍
- # 读 Android(安卓)开发艺术探索 &8
- Android学习路线(二十七)键值对(SharedPreferences)存储
- Android系统的启动流程
- Android(安卓)Looper
- Android界面刷新的方法
- 转:编写高效的Android代码
- 使用线程更新UI