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等方法发送的为延迟消息)。

更多相关文章

  1. Android(安卓)Studio真机测试时生成的程序出现闪退
  2. Android网络请求框架AsyncHttpClient (android-async-http)介绍
  3. # 读 Android(安卓)开发艺术探索 &8
  4. Android学习路线(二十七)键值对(SharedPreferences)存储
  5. Android系统的启动流程
  6. Android(安卓)Looper
  7. Android界面刷新的方法
  8. 转:编写高效的Android代码
  9. 使用线程更新UI

随机推荐

  1. android 事件模型
  2. ios 开发之基础控件
  3. Android(安卓)开发环境安装
  4. stagefright概述
  5. Android系统启动流程 -- linux kernel
  6. 【Android(安卓)声音处理】MediaPlayer和
  7. Android(安卓)View 事件分发机制详解
  8. android相对布局--计算器的例子
  9. Android(安卓)学习之- 单选按钮、复选框
  10. 如何添加一个Application Framework Serv