源码解析-----HandlerThread

                          Android HandlerThread 彻底解析

一、概述

HandlerThread继承于Thread,因此它本质就是个Thread。与普通Thread的差异就在于,主要的做用是创建了一个线程,而且创立了消息队列,有来本身的looper,可让咱们在本身的线程中分发和处理消息。android

二、HandlerThread实例

public class HandlerThreadActivity extends AppCompatActivity
{

    private TextView mTvServiceInfo;

    private HandlerThread mCheckMsgThread;
    private Handler mCheckMsgHandler;
    private boolean isUpdateInfo;

    private static final int MSG_UPDATE_INFO = 0x110;

    //与UI线程管理的handler
    private Handler mHandler = new Handler();


    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_thread_handler);

        //建立后台线程
        initBackThread();

        mTvServiceInfo = (TextView) findViewById(R.id.id_textview);

    }

    @Override
    protected void onResume()
    {
        super.onResume();
        //开始查询
        isUpdateInfo = true;
        mCheckMsgHandler.sendEmptyMessage(MSG_UPDATE_INFO);
    }

    @Override
    protected void onPause()
    {
        super.onPause();
        //中止查询
        isUpdateInfo = false;
        mCheckMsgHandler.removeMessages(MSG_UPDATE_INFO);

    }

    private void initBackThread()
    {
        mCheckMsgThread = new HandlerThread("check-message-coming");
        mCheckMsgThread.start();
        mCheckMsgHandler = new Handler(mCheckMsgThread.getLooper())
        {
            @Override
            public void handleMessage(Message msg)
            {
                checkForUpdate();
                if (isUpdateInfo)
                {
                    mCheckMsgHandler.sendEmptyMessageDelayed(MSG_UPDATE_INFO, 1000);
                }
            }
        };


    }

    /**
     * 模拟从服务器解析数据
     */
    private void checkForUpdate()
    {
        try
        {
            //模拟耗时
            Thread.sleep(1000);
            mHandler.post(new Runnable()
            {
                @Override
                public void run()
                {
                    String result = "实时更新中,当前大盘指数:<font color='red'>%d</font>";
                    result = String.format(result, (int) (Math.random() * 3000 + 1000));
                    mTvServiceInfo.setText(Html.fromHtml(result));
                }
            });

        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }

    }

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        //释放资源
        mCheckMsgThread.quit();
    }


}

代码的说明:服务器

能够看到咱们在onCreate中,去建立和启动了HandlerThread,而且关联了一个mCheckMsgHandler。而后咱们分别在onResume和onPause中去开启和暂停咱们的查询,最后在onDestory中去释放资源。dom

这样就实现了咱们每隔5s去服务端查询最新的数据,而后更新咱们的UI,固然咱们这里经过Thread.sleep()模拟耗时,返回了一个随机数,你们能够很轻易的换成真正的数据接口。ide

3.HandlerThread 源码分析

mCheckMsgThread = new HandlerThread("check-message-coming");
 mCheckMsgThread.start();

建立和启动的对象,那么随便扫一眼:对应的源码oop

package android.os;


public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    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;
    }

源码解释:源码分析

看到了什么,其实咱们就是初始化和启动了一个线程;而后咱们看run()方法,能够看到该方法中调用了Looper.prepare(),Loop.loop();post

prepare()呢,中建立了一个Looper对象,而且把该对象放到了该线程范围内的变量中(sThreadLocal),在Looper对象的构造过程当中,初始化了一个MessageQueue,做为该Looper对象成员变量。ui

loop()就开启了,不断的循环从MessageQueue中取消息处理了,当没有消息的时候会阻塞,有消息的到来的时候会唤醒。若是你不明白我说的,参考上面推荐的文章。this

 

接下来,咱们建立了一个mCheckMsgHandler,是这么建立的:spa

mCheckMsgHandler = new Handler(mCheckMsgThread.getLooper())

对应源码:

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;
    }

源码解释:

mCheckMsgThread.getLooper()返回的就是咱们在run方法中建立的mLooper。

那么Handler的构造呢,其实就是在Handler中持有一个指向该Looper.mQueue对象,当handler调用sendMessage方法时,其实就是往该mQueue中去插入一个message,而后Looper.loop()就会取出执行。

好了,到这咱们就分析完了,其实就几行代码;不过有一点我想提一下:

若是你够细心你会发现,run方法里面当mLooper建立完成后有个notifyAll(),getLooper()中有个wait(),这是为何呢?由于的mLooper在一个线程中执行,而咱们的handler是在UI线程初始化的,也就是说,咱们必须等到mLooper建立完成,才能正确的返回getLooper();wait(),notify()就是为了解决这两个线程的同步问题。

相关文章
相关标签/搜索