文章目錄
Android
安卓開發者指南:https://developer.android.google.cn/guide
1 Handler
1.1 概念
Handler:消息分發對象,進行發送和處理消息,並且其Runable對象和一個線程的MessageQueue關聯。
爲什麼要使用Handler:解決子線程如何通知UI組件更新的問題,實現了不同線程間通信的一種機制。消息調度,將一個任務切換到某個指定的線程中去執行。多個線程併發更新UI的同時,保證線程安全。
通信機制
Handler機制的核心類:
1.Handler:作用就是發送與處理信息,如果希望Handler正常工作,在當前線程中要有一個Looper對象;
2.Looper類:爲一個線程開啓一個消息循環。通過MessageQueue來存放消息和事件,一個線程只能有一個 Looper,對應一個MessageQueue。Looper.prepare(),Looper.loop()(注意,寫在Looper.loop之後的代碼不會被執行,這個函數內部是一個循環)
3.Message:Handler接收與處理的消息對象
4.MessageQueue:消息隊列,先進先出管理Message,在初始化Looper對象時會創建一個與之關聯的MessageQueue;
UI線程:就是主線程,系統在創建UI線程的時候會初始化一個Looper對象,同時也會創建一個與其關聯的MessageQueue。
1.2 Handler使用
相關方法:
void handleMessage(Message msg):處理消息的方法,通常是用於被重寫
sendEmptyMessage(int what):發送空消息
sendEmptyMessageDelayed(int what,long delayMillis):指定延時多少毫秒後發送空信息
sendMessage(Message msg):立即發送信息
sendMessageDelayed(Message msg):指定延時多少毫秒後發送信息
final boolean hasMessage(int what):檢查消息隊列中是否包含what屬性爲指定值的消息 如果是參數爲(int what,Object object):除了判斷what屬性,還需要判斷Object屬性是否爲指定對象的消息
方式一: post(Runnable)
創建一個工作線程,實現 Runnable 接口,實現 run 方法,處理耗時操作;
創建一個 handler,通過 handler.post/postDelay,投遞創建的 Runnable,在 run 方法中進行更新 UI 操作。
new Thread(new Runnable() {
@Override
public void run() {
/**
耗時操作
*/
handler.post(new Runnable() {
@Override
public void run() {
/**
更新UI
*/
}
});
}
}).start();
方式二: sendMessage(Message)
創建一個工作線程,繼承 Thread,重新 run 方法,處理耗時操作;
創建一個 Message 對象,設置 what 標誌及數據
通過 sendMessage 進行投遞消息
創建一個handler,重寫 handleMessage 方法,根據 msg.what 信息判斷,接收對應的信息,再在這裏更新 UI。
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) { //判斷標誌位
case 1:
/**
獲取數據,更新UI
*/
break;
}
}
};
public class WorkThread extends Thread {
@Override
public void run() {
super.run();
/**
耗時操作
*/
//從全局池中返回一個message實例,避免多次創建message(如new Message)
Message msg =Message.obtain();
msg.obj = data;
msg.what=1; //標誌消息的標誌
handler.sendMessage(msg);
}
}
new WorkThread().start();
1.3 Handler 存在的問題
1.UI線程/主線程/ActivityThread
2.線程不安全
3.消息循環機制:Looper
內存方面
Handler 被作爲 Activity 引用,如果爲非靜態內部類,則會引用外部類對象。當 Activity finish 時,Handler可能並未執行完,從而引起 Activity 的內存泄漏。故而在所有調用 Handler 的地方,都用靜態內部類。
異常方面
當 Activity finish 時,在 onDestroy 方法中釋放了一些資源。此時 Handler 執行到 handlerMessage 方法,但相關資源已經被釋放,從而引起空指針的異常。
避免
如果是使用 handlerMessage,則在方法中加try catch。
如果是用 post 方法,則在Runnable方法中加try catch。
Handler 的改進
內存方面:使用靜態內部類創建 handler 對象,且對 Activity 持有弱引用。
異常方面:不加 try catch,而是在 onDestory 中把消息隊列 MessageQueue 中的消息給 remove 掉。
作者:空心散人
鏈接:https://www.jianshu.com/p/0a274564a4b1
來源:簡書
1.4 Handler實踐的三種效果
應用場景:
1.To schedule messages and runnables to be executed as some point in the future
2.To enqueue an action to be performed on a different thread than your own.
創建Handler,重寫方法handleMessage(Message msg)
UI線程做輕量級操作
1.Handler. sendMessage()
2.Handler.post()
3.handleMessage(Message msg)
- 異步下載文件更新進度條
下載,讀寫權限,AndroidManifest.xml:
DownloadActivity.java:主線程–> start
點擊按鍵
發起下載
開啓子線程做下載
下載過程中通知主線程 --> 主線程更新進度條
- 倒計時的實現
- 用Handler來實現簡單打地鼠遊戲
< ImageView>、< Button>、< TextView>
Activity實現View.OnClickListener接口,initView(),重寫方法onClick();二維數組模擬隨機座標
2 異步任務
2.1 AsyncTask
異步,相當於多個線程,同時進行
多線程提高效率
ANR(Application Not Responding)應用程序無響應,由多線程引起的事件。
1.Main/UI Thread和Worker Thread
2. Main/UI Thread和Worker Thread之間的通信
3. Thread / Runnable線程安全
4.普通的主線程更新
Activity.runOnUiThread(Runpable)
View.post(Runnable)
View.postDelayed(Runnable, long)
異步加載實現方式:AsyncTask,多線程或者線程池
AsyncTask好處:封裝並簡化了異步操作,方便後臺線程操作後更新UI,實現了Thread和Handler的封裝,實質:Handler異步消息處理機制
常用方法:
1.泛型參數: <Params,Progress,Result>
2. UI操作 onPreExecute執行前 操作前準備工作,onPostExecute執行後在主線程中 執行結果處理
3.後臺線程操作doInBackground執行中執行耗時操作
4.輸入輸出Params, Result
5.進度顯示onProgressUpdate,收到進度然後處理,也是在UI線程中
6.取消onCancelled(Boolean aBoolean)、onCancelled()
2.2 網絡下載demo
- 網絡上請求數據:申請網絡權限,讀寫存儲權限
- 設計界面,佈局layout
ProgressBar,Button,TextView
AsyncTask.java
- 下載前,UI
- 下載中,數據
在另外一個線程中處理數據
- 下載後,UI