首页 > 系统 > Android > 正文

实例分析Android中HandlerThread线程用法

2019-10-22 18:20:18
字体:
来源:转载
供稿:网友

一、HandlerThread的介绍及使用举例             

HandlerThread是什么鬼?其本质就是一个线程,但是HandlerThread在启动的时候会帮我们准备好一个Looper,并供外界使用,说白了就是使我们在子线程中更方便的使用Handler,比如没有HandlerThread我们要在子线程使用Handler,写法如下:

private Handler mHandler;    @Override     public void run() {        super.run();         Looper.prepare();         mHandler = new Handler(){             @Override             public void handleMessage(Message msg) {             }         };         Looper.loop();}

有了HandlerThread就不用我们自己管理Looper了,至于为什么分析源码的时候就明白了。

HandlerThread使用简单介绍:

首先我们要初始化HandlerThread然后调用其start方法,也就是开启线程:

mHandlerThread = new HandlerThread("mHandlerThread");//这里的mHandlerThread其实就是线程的名字mHandlerThread.start();

接下来初始化一个Handler并且将mHandlerThread中的Looper作为构造函数参数传递给Handler:

mHandler = new Handler(mHandlerThread.getLooper())

这样就保证了Hnadler运行在子线程。并且需要在适合的时机调用HandlerThread的quit方法或quitSafely方法,如Activity销毁的时候:

@Overrideprotected void onDestroy() {   //   super.onDestroy();   //释放资源   mHandlerThread.quit();}

quit()与quitSafely()方法比较(这里只说一些结论,源码可以自己查看):

相同点:

调用之后MessageQueue消息队列均不在接受新的消息加入队列。

不同点:

quit方法把MessageQueue消息池中所有的消息全部清空。quitSafely方法只会清空MessageQueue消息池中所有的延迟消息(延迟消息是指通过sendMessageDelayed或postDelayed等方法发送的消息),非延迟消息则不清除继续派发出去让Handler去处理。

接下来我们完整看一下HandlerThread例子源码:

 public class MainActivity extends Activity {     private HandlerThread mHandlerThread;     private Handler mHandler;     private boolean flag;     //     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);        mHandlerThread = new HandlerThread("mHandlerThread");         mHandlerThread.start();         mHandler = new Handler(mHandlerThread.getLooper()) {             @Override             public void handleMessage(Message msg) {                 //                 try {                     Thread.sleep(2000);                 } catch (InterruptedException e) {                     e.printStackTrace();                 }                 if(flag){                     Log.i("HandlerThread", "更新:"+new Random().nextInt(1000));                 }                 mHandler.sendEmptyMessage(1);             }         };     }     @Override     protected void onResume() {         //         super.onResume();         flag = true;         mHandler.sendEmptyMessage(1);     }     @Override     protected void onPause() {         //         super.onPause();         flag = false;     }     @Override     protected void onDestroy() {         //         super.onDestroy();         //释放资源         mHandlerThread.quit();     }}

运行程序就会在控制台看到每隔两秒有Log打出。至于HandlerThrea的使用就到此为止了,看懂上面小例子就差不多了。

二、HandlerThread的源码分析

HandlerThread源码非常简短,出去注释不到100行,这里就直接全部贴出来了:

 public class HandlerThread extends Thread {     int mPriority;     int mTid = -1;    Looper mLooper;     public HandlerThread(String name) {         super(name);        mPriority = Process.THREAD_PRIORITY_DEFAULT;    }     /**     * Constructs a HandlerThread.     * @param name     * @param priority The priority to run the thread at. The value supplied must be from      * {@link android.os.Process} and not from java.lang.Thread.      */    public HandlerThread(String name, int priority) {        super(name);        mPriority = priority;     }    /**      * Call back method that can be explicitly overridden if needed to execute some      * setup before Looper loops.     */     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;     }     /**      * This method returns the Looper associated with this thread. If this thread not been started      * or for any reason is isAlive() returns false, this method will return null. If this thread       * has been started, this method will block until the looper has been initialized.        * @return The looper.      */     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;     }     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;     }     /**      * Returns the identifier of this thread. See Process.myTid().      */     public int getThreadId() {         return mTid;     } }

看第一行就知道了其本质就是一个线程。

6-9行以及17-20行构造函数,也很简单,就是初始化的时候我们可以定义线程名字,还可以传入线程优先级。

初始化完成,紧接着调用start()开发线程就会执行run方法逻辑。

30-41行代码,最重要的就是调用Looper.prepare()以及Looper.loop()方法为我们在子线程准备好一个Looper。并且用变量mLooper记录,调用getLooper()方法的时候返回。

但是,细心的你肯定发现run()方法中有个notifyAll(),getLooper()中有个wait()为什么要加这些鸟玩意?

大家发现没在HandlerThread 例子中Handler的创建是在主线程完成的,创建的时候需要调用HandlerThread的getLooper()获取mLooper作为参数传递给Handler的构造函数,而Looper的创建是在子线程中创建的,这里就有线程同步问题了,比如我们调用getLooper()的时候HandlerThread中run()方法还没执行完,mLooper变量还未赋值,此时就执行了wait()等待逻辑,一直等到run()方法中mLooper被赋值,之后立即执行notifyAll(),然后getLooper()就可以正确返回mLooper了。

明白了吧,不明的话这里需要花些时间好好理解下,好了源码主要部分就分析完了,看到这里相信你对HandlerThread有了一定的了解了。

HandlerThread 还是比较简单理解的,好了,本篇到此为止,希望对你有帮助。


注:相关教程知识阅读请移步到Android开发频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表