在開發過程當中咱們可使用HandlerThread建立隊列,經過發送消息讓線程處理任務,重複利用線程節省系統資源開銷。能夠是使用IntentService來解決Service中不能處理耗時操做的問題。本篇文章主要從基本使用和核心源碼分析,兩個方面來介紹HandlerThread和IntentService。android
下面爲一張流程圖,在文章的HandlerThread和IntentService的源碼分析過程當中能夠參考這張圖。bash
HandlerThread是Android自帶的一個輕量級的異步處理的類,該類繼承Thread具備Thread和Handler的特性。異步
注:HandlerThread的執行流程能夠參考文章開始圖片右上角部分。ide
建立Handler.Callback函數
private Handler.Callback mHandlerCallback = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case 123:
Log.i(TAG, (String) msg.obj + "【線程名爲】:" +
mHandler.getLooper().getThread().getName());
break;
}
return false;
}
};
複製代碼
建立Hanlder和HandlerThreadoop
private Handler mHandler;
private HandlerThread mHandlerThread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandlerThread = new HandlerThread("建立HandlerThread線程");
mHandlerThread.start();
//使用Callback和子線程的Looper建立Handler
mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
}
複製代碼
發送消息源碼分析
switch (v.getId()) {
case R.id.mBnt_handlerThread:
//發送消息
Message message = mHandler.obtainMessage(123, "這是HandlerThread發送的消息");
message.sendToTarget();
break;
}
複製代碼
執行結果:性能
I/MainActivity: 這是HandlerThread發送的消息【線程名爲】:建立HandlerThread線程
複製代碼
結束:ui
protected void onDestroy() {
super.onDestroy();
//馬上清楚
mHandlerThread.quit();
//消息隊列執行完以後再清除
mHandlerThread.quitSafely();
}
複製代碼
咱們從上面的基本使用建立Hanlder的時候應該能夠看出,Hanlder的建立使用了HanlderThread的Looper。咱們知道一個線程中只能有一個Looper,咱們平時使用Handler發送消息使用的是主線程的Looper,所以消息是在主線程中執行的。可是咱們經過下面這種指定子線程Looper的來建立Handler,那麼消息將會在子線程中執行:this
mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
複製代碼
HandlerThread的Looper建立是在run()方法中建立的,它會先調用Looper.prepare()
來建立Looper,將建立好的Looper賦值給mLooper
這個成員變量咱們會在IntentService的時候看到它。而後會設置線程的優先級,最後是調用Looper.loop()
開啓循環。下面爲建立代碼:
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
複製代碼
從上面的代碼中讀者可能發如今線程優先級設置完成後,緊接着就調用onLooperPrepared()
函數。那麼這個函數又是幹嗎的呢?其實這個函數是一個空實現函數,開發人員能夠根據本身的須要來實現,能夠在裏面作一些初始化的操做等。
protected void onLooperPrepared() {}
複製代碼
其實HandlerThread最核心的就是run()方法看完上面的內容,基本是上就明白HandlerThread的執行過程。當咱們在銷燬的時候能夠經過它的quit()
和quitSafely()
方法,這兩個方法內部調用的是Looper的方法:
//清除所有消息
public boolean quit() {
Looper looper = getLooper();
if (looper != null) {
looper.quit();
return true;
}
return false;
}
//清除延遲消息,不是延遲消息將會繼續執行.
//直到隊列中沒有了消息,Looper纔會被銷燬.
public boolean quitSafely() {
Looper looper = getLooper();
if (looper != null) {
looper.quitSafely();
return true;
}
return false;
}
複製代碼
IntentService繼承Service,因此它本質上是一個Service。不一樣的是它在本身內部能夠經過HandlerThread,Handler來執行耗時操做。
注:IntentService的執行流程能夠參考文章一開始的圖片
IntentService的使用也很簡單,先建立IntentService子類,而且實現onHandleIntent()方法
public class MyIntentService extends IntentService {
private final String TAG = "MyIntentService";
/**
* 注意將自動生成的有參書構造改爲無參構造
* super()中必須填入線程的名字
*/
public MyIntentService() {
super("IntentService線程");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
String extra = intent.getStringExtra("MyIntentService");
Log.i(TAG, "傳入的內容爲:" + extra + "【線程名爲】:" + Thread.currentThread().getName());
}
}
複製代碼
配置AndroidManifest.xml
<service android:name=".MyIntentService"/>
複製代碼
在Activity中調用
case R.id.mBnt_intentService:
Intent intentService = new Intent(MainActivity.this,
MyIntentService.class);
intentService.putExtra("MyIntentService", "數據123");
//啓動intentservice
startService(intentService);
break;
複製代碼
IntentServiceonCreat()方法分別建立了HandlerThread和ServiceHandler兩個對象,HandlerThread對象咱們上面內容介紹過,讀者若是不清楚能夠返回去看看;而ServiceHandler對象是一個繼承Handler的類,這個類會在後面介紹到,咱們先暫時知道建立該函數須要指定Looper就能夠了。從下面的源碼中咱們很容易明白,thread在開啓線程後,IntentService又獲取了HandlerThread的Looper並用它來建立了Hanlder從而把IntentService、HanlderThread和Handler關聯起來了。
注:IntentService本質上是一個service,所以同一個Intentservice只會建立一次,即它的onCreate()只會調用一次;不過它的onStartCommand()和onStart()會調用屢次。
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
複製代碼
當咱們經過startService()
啓動IntentService的時候它會執行:
onCreate()-->onStartCommand()-->onStart()
複製代碼
其中onStart()方法會發送消息通知Handler執行任務。
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
複製代碼
從上面的代碼咱們能夠知道,onStart()中將咱們在Activity傳入的intent和startId包裝到Message中並將它發送給Handler。
上面咱們在onCreate()方法中提到過ServiceHandler這個類繼承Handler,它也是消息的處理類。任務執行會在該類的handleMessage()
方法中調用onHandleIntent()
方法來異步執行。下面爲ServiceHandler的源碼:
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
複製代碼
咱們在onClick的方法中建立該類對象的時候傳入了HandlerThread對象的Looper,所以消息的執行是在子線程執行。handleMessage()方法將Message的Intent取出後又交給了onHandleIntent()方法處理,該方法是一個抽象函數須要開發者根據業務本身實現。當onHandleIntent()任務執行完後就會調用stopSelf()
關閉服務。
在開發過程當中可以合理的使用HanlderThread和IntentService可以有效程序的性能。須要注意的是HandlerThread由於是使用了消息隊列,所以任務是串行執行的這點須要咱們注意。