【齊天的部落格】轉載請注明出處(萬分感謝!):
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 = ;
//與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, );
}
}
};
}
/**
* 模拟從伺服器解析資料
*/
private void checkForUpdate()
{
try
{
//模拟耗時
Thread.sleep();
mHandler.post(new Runnable()
{
@Override
public void run()
{
String result = "實時更新中,目前大盤指數:<font color='red'>%d</font>";
result = String.format(result, (int) (Math.random() * + ));
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 = -; }
在之前Android多線程(Handler篇)中可以知道:
prepare()中建立了一個Looper對象,并放入ThreadLocal中,在Looper對象的構造過程中,初始化了并綁定了一個MessageQueue。
loop()方法不斷的循環從MessageQueue中取消息處理,當沒有消息的時候會阻塞,有消息的到來的時候會喚醒。
- 建立
傳回了剛剛在run()中建立的mLooper對象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()中的notifyAll()和getLooper()中的wait();
因為Handler是在主線程初始化的,是以必須等mLooper建立完成才能getLooper(),是以當mLooper==null時getLoop等待一下mLooper初始化,得到以後notifyAll。