【多線程】九、Android異步任務

相關文章:
【多線程】一、線程狀態切換
【多線程】二、線程優先級&守護線程
【多線程】三、線程訪問變量
【多線程】四、線程異常抓捕
【多線程】五、線程池
【多線程】六、鎖與同步
【多線程】七、阻塞隊列
【多線程】八、異步計算結果獲取
【多線程】九、Android異步任務

Handler機制解析

相關 用途 說明
MessageQueue 消息隊列容器 單鏈表實現
(1)enqueueMessage:添加消息必要時喚醒next
(2)next:讀取消息,無消息時阻塞
Looper 消息循環讀取器 (1)Looper.prepare():創建MessageQueue
(2)Looper.loop():啓動無限循環調MessageQueue.next()
若返回null退出;非null則調Message#target.dispatchMessage()
Handler 消息發送和處理器 (1)發送:
Handler#post
Hanlder#sendMessage
Looper::myLooper().messageQueue#enqueueMessage;
(2)處理:
Hanlder#dispatchMessage
Message#callback
Hanlder#Callback#handleMessage
Handler#handleMessage
ThreadLocal 保障Looper互不干擾 線程全局變量,原理似HashMap<Thread,T>

消息處理示例

private volatile Handler mHandler;

private Handler.Callback mCallback = new Handler.Callback() {
	@Override
	public boolean handleMessage(Message msg) {
		Log.e(TAG, "handleMessage: " + Thread.currentThread());
		// 執行完畢退出loop循環,銷燬Thread
		if(null != Looper.myLooper()){
			Looper.myLooper().quitSafely();
		}
		// Looper#quit 方法會立即退出,quitSafely會在消息處理完畢後退出;
		// Looper退出後,Handler#send返回false發送消息失敗;
		return true;
	}
};

private Runnable mRunnable = new Runnable() {
	@Override
	public void run() {
		Looper.prepare();
		// Handler在哪個線程創建就在哪個線程處理
		mHandler = new Handler(mCallback);
		Looper.loop();
	}
};
// =============== 切線程示例 ===============
// 創建處理線程
new Thread(mRunnable, "Thread-0").start();

// 在其他線程發起消息
new Thread(new Runnable() {
	@Override
	public void run() {
		// 切到Thread-0
		mHandler.sendEmptyMessage(0x00);
	}
},"Thread-1").start();

View單線程模型
爲保證View狀態和操作簡單保障性能,ViewRoomImpl會checkThread,以保證在主線程操作UI(ActivityThread#main:Looper.prepareMainLooper)

主線程Looper
AMS中的回調運行在Binder線程池,通過ActivityThread#H切換到主線程處理各組件生命週期;主線程Looper初始化過程見ActivityThread::main

執行異步任務的方式

方式 使用 說明
AsyncTask 串行啓動:task.execute(param1,param2)
並行啓動:task.executeOnExecutor(params)
適用輕量級異步任務,便於更新UI
一個AsyncTask對象只能調用execute一次
多個Task在1.6之前和3.0之後默認串行執行
HandlerThread (1)異步Handler:
創建HanlderThread並start
用它的Looper創建Handler
使用完畢後HandlerThread#quit
(2)IntentService
Android在IntentService#OnCreate
中創建了HanlderThreadstart了;
具有Looper的Thread
注意start(Looper#loop)是阻塞的需手動quit
IntentService Context#startService(Intent) 適用高優先級需報活的耗時任務
能自動退出,比Thread更易保活;
Executor execute(),submit() 複用Thread對象, 減少線程建銷成本

AsyncTask解析

class AsyncTask<Params,Progress,Result>{
	// 主線程,準備執行;
	onPreExecute();
	// 工作線程池 AsyncTask::SERIAL_EXECUTOR/THREAD_POOL_EXECUTOR
	doInBackground(Params...params);
	// 主線程,進度已更新;
	onProgressUpdate(Progress...progress);
	// 主線程,任務完成;
	onPostExecute(Result result)
	// 主線程,任務取消;
	onCancelled();

	// 通知進度更新
	publishProgress();
	// 查詢是否被外部取消
	isCancelled();
}
工作流程:
AsyncTask#execute
-> AsyncTask#executeOnExecutor
-> SerialExecutor#execute-> ThreadPoolExecutor#execute

-> FutureTask#run -> WorkerRunnable#call

-> AsyncTask#doInBackground -> AsyncTask#postResult 
-> InternalHandler#handleMessage -> AsyncTask#finish
-> AsyncTask#onPostExecute / onCancelled

IntentService解析

Created with Raphaël 2.2.0ContextImpl#startService已創建?onStartCoommondonStart(已調stopSelf)onHandleIntent(Intent)stopSelf(startId)AMS#stopServiceTokenActiveServices#stopServiceTokenLockedonDestroyHandlerThread#quitonCreateyesno

注:

  1. stopSelf(startId): 如果所有任務執行完畢(laststartId==startId?)則退出(當startId=-1立即退出);
  2. 由於Looper是串行處理消息,所以一個IntentService的多個Intent任務也是串行處理的;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章