源碼解析-----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()就是爲了解決這兩個線程的同步問題。

相關文章
相關標籤/搜索