Android 之 Handler
前言:
本編文章純粹個人見解,如有錯誤或者不到位的地方,請大家指出,多謝。
組成:
一、Message
二、Handler
三、MessageQueue
四、Looper
介紹:
Message:
執行緒間通訊的資訊載體。
可將關鍵的物件,資料裝在一個Message類中發給其他執行緒(一般是主執行緒)。
Handler:
主要負責傳送和處理Message。
MessageQueue:
主要負責存放由handler發出的Message。
每個執行緒只有一個MessageQueue物件。
Looper:
主要負責將MessageQueue中的Message拿個Handler處理。
每個執行緒只有一個Looper物件。
大致流程圖:
上圖來自郭霖的 《第一行程式碼》
(子)Handler → Message → MessageQueue → Message → Looper → Message → (主)Handler
如何使用:
第一步:在主執行緒新建一個Handler並重寫handleMessage()方法。
第二步:在子執行緒新建一個Message類並打包好要傳送的資料,呼叫handler.sendMessage()。
先來一個簡單的例子:
子執行緒傳送訊息,改變button的內部文字
public class MainActivity extends AppCompatActivity { private Button sendBtn; private static final int CHANGE_BUTTON = 1; private Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case CHANGE_BUTTON: sendBtn.setText("Handler"); break; } //以前handlerMessage沒有返回值,現在要返回boolean //應該是根據boolean值判斷handleMessage方法是否執行完畢 return true; } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sendBtn = findViewById(R.id.sendBtn); sendBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { Message msg = new Message(); msg.what = CHANGE_BUTTON; mHandler.sendMessage(msg); } }).start(); } }); } }
效果圖:
Message可以包含什麼資訊呢?
如果你覺得上面的博文還是不夠包含你想傳送的資訊。
你可以自己建立一個類,把你想發的資訊都裝進去。
我做個小小的例子:
1.寫個實體類
2.將實體類放進Bundle裡,再將Bundle放進Message裡
public class Data implements Serializable{
private String str;
private long l;
private float flo;
/* 以下省略setter 和 getter */
}
sendBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
//設定好自定義的實體類
Data data = new Data();
data.setStr("hello");
data.setL(32464651231234L);
data.setFlo(1.67f);
//將實體類放進Bundle裡
Bundle mBundle = new Bundle();
mBundle.putSerializable("SER_KEY", data);
//使用setData將想傳送的資訊一起發出去
Message msg = new Message();
msg.what = CHANGE_BUTTON;
msg.setData(mBundle);
mHandler.sendMessage(msg);
}
}).start();
}
});
private Handler mHandler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case CHANGE_BUTTON:
Bundle bundle = msg.getData();
Data data = (Data) bundle.getSerializable("SER_KEY");
if (data != null) {
sendBtn.setText(data.getStr());
}
break;
}
return true;
}
});
Handler的優缺點:
優點:
結構比較清晰,如果有多個後臺任務並行進行多個UI操作,Handler是很方便的。
缺點:
如果只有一個後臺任務那就會顯得程式碼過多和結構複雜。
因為我的例子只有封裝資訊,
根本沒有進行後臺耗時操作,例如I/O,網路,資料庫操作,所以感覺不出來。