Android多线程(HandlerThread篇)

【齐天的博客】转载请注明出处(万分感谢!): 
https://blog.csdn.net/qijinglai/article/details/80735718

关联文章: 
Android多线程(Handler篇) 
Android多线程(AsyncTask篇) 
Android多线程(HandlerThread篇) 
Android多线程(IntentService篇)

在之前Android多线程(Handler篇)中讲解了ThreadLoacl、Looper、Handler、Message之间的关系,在主线程中为我们工作。其实我们可以借鉴UI线程Looper的思想,建一个子线程,也通过Handler、Looper通信,可以适用于很多场景。 
主线程中是自带looper的,而在子线程中使用Handler需要自己创建looper,而HandlerThread的注释中说:

Handy class for starting a new thread that has a looper. 
The looper can then be used to create handler classes. 
Note that start() must still be called.

意思是,使用HandlerThread可以方便的开启一个线程,并且这个线程已经绑定了一个looper了。这个looper可以用来new一个handler类。注意在此之前,要调用start()方法。 
很显然HandlerThread可以胜任我们提到的工作。

使用
这里就直接复制鸿洋_写的例子了

import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.widget.TextView;

public class MainActivity 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_main);

        //创建后台线程
        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();
    }
}

布局就是一个TextView。 
使用并不是本文重点,下面分析源码。

原理分析
HandlerThread使用一共三步

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

构造,开启,创建

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

只是调用了父类的初始化方法开了一个线程

开启 
调用start()方法,启动一个新线程,新线程会执行相应的run()方法:

@Override
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

在之前Android多线程(Handler篇)中可以知道: 
prepare()中创建了一个Looper对象,并放入ThreadLocal中,在Looper对象的构造过程中,初始化了并绑定了一个MessageQueue。 
loop()方法不断的循环从MessageQueue中取消息处理,当没有消息的时候会阻塞,有消息的到来的时候会唤醒。

创建

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

返回了刚刚在run()中创建的mLooper对象

最后值得说一下的是run()中的notifyAll()和getLooper()中的wait(); 
因为Handler是在主线程初始化的,所以必须等mLooper创建完成才能getLooper(),所以当mLooper==null时getLoop等待一下mLooper初始化,得到以后notifyAll。
--------------------- 
作者:Qi T 
来源:CSDN 
原文:https://blog.csdn.net/qijinglai/article/details/80735718 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/baidu_32472003/article/details/89631638
今日推荐