Android消息機(jī)制Handler用法總結(jié)
1.簡(jiǎn)述
Handler消息機(jī)制主要包括: MessageQueue、 Handler、 Looper、Message。
- Message:需要傳遞的消息,可以傳遞數(shù)據(jù);
- MessageQueue:消息隊(duì)列,但是它的內(nèi)部實(shí)現(xiàn)并不是用的隊(duì)列,而是通過(guò)單鏈表的數(shù)據(jù)結(jié)構(gòu)來(lái)維護(hù)消息列表,因?yàn)閱捂湵碓诓迦牒蛣h除上比較有優(yōu)勢(shì)。主要功能是向消息池投遞消息( MessageQueue.enqueueMessage)和取走消息池的消息( MessageQueue.next)。?
- Handler:消息輔助類(lèi),主要功能是向消息池發(fā)送各種消息事件( Handler.sendMessage)和處理相應(yīng)消息事件( Handler.handleMessage);?
- Looper:消息控制器,不斷循環(huán)執(zhí)行( Looper.loop),從MessageQueue中讀取消息,按分發(fā)機(jī)制將消息分發(fā)給目標(biāo)處理者。
2.異步線程切換原理
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
每一個(gè)異步線程,都維護(hù)著唯一的一個(gè)Looper,每一個(gè)Looper會(huì)初始化(維護(hù))一個(gè)MessageQueue,之后進(jìn)入一個(gè)無(wú)限循環(huán)一直在讀取MessageQueue中存儲(chǔ)的消息,如果沒(méi)有消息那就一直阻塞等待。
我們?cè)趯?shí)例化handler的過(guò)程中,會(huì)先得到當(dāng)前所在線程的looper對(duì)象,之后得到與該looper對(duì)象相對(duì)應(yīng)的消息隊(duì)列,看源碼Handler中持有Looper、MessageQueue。
private static void handleCallback(Message message) {
message.callback.run();
}
final Looper mLooper;
final MessageQueue mQueue;
final Callback mCallback;
當(dāng)我們發(fā)送消息的時(shí)候,即handler.sendMessage或者h(yuǎn)andler.post,會(huì)將msg中的target賦值為handler自身,這就是實(shí)現(xiàn)message從一個(gè)線程到另外一個(gè)線程的傳遞的本質(zhì),之后加入到消息隊(duì)列中。
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
我們一般會(huì)重寫(xiě)handlerMessage方法處理消息,這將會(huì)在msg.target.disPatchMessage方法中被回調(diào),從而實(shí)現(xiàn)了message從一個(gè)線程到另外一個(gè)線程的傳遞。
3.總結(jié)
- 1.Handler 的背后有 Looper、MessageQueue 支撐,Looper 負(fù)責(zé)消息分發(fā),MessageQueue 負(fù)責(zé)消息管理;
- 2.在創(chuàng)建 Handler 之前一定需要先創(chuàng)建 Looper,Looper 有退出的功能,但是主線程的 Looper 不允許退出;
- 3.異步線程Looper,Looper.prepare()創(chuàng)建Looper,Looper.loop()開(kāi)始輪詢,需要自己調(diào)用 Looper.myLooper().quit()退出;
- 4.Runnable 被封裝進(jìn)了 Message,可以說(shuō)是一個(gè)特殊的 Message;
- 5.Handler.handleMessage() 所在的線程是 Looper.loop() 方法被調(diào)用的線程;
- 6.Handler內(nèi)存泄漏的原因
原因:MessageQueue持有Message,Message持有activity,delay多久,message就會(huì)持有activity多久。
解決方案:靜態(tài)內(nèi)部類(lèi)、弱引用,最后不要忘記調(diào)用Handler.removeCallbacksAndMessages(null)清空所有消息。
public class SampleActivity extends Activity {
/**
* Instances of static inner classes do not hold an implicit
* reference to their outer class.
*/
private static class MyHandler extends Handler {
private final WeakReference<SampleActivity> mActivity;
public MyHandler(SampleActivity activity) {
mActivity = new WeakReference<SampleActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
SampleActivity activity = mActivity.get();
if (activity != null) {
// ...
}
}
}
// MyHandler
private final MyHandler mHandler = new MyHandler(this);
/**
* Instances of anonymous classes do not hold an implicit
* reference to their outer class when they are "static".
*/
private static final Runnable sRunnable = new Runnable() {
@Override
public void run() { /* ... */ }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Post a message and delay its execution for 10 minutes.
mHandler.postDelayed(sRunnable, 1000 * 60 * 10);
// Go back to the previous Activity.
finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
//mHandler.removeCallbacksAndMessages(null);
}
}
以上所述是小編給大家介紹的Android消息機(jī)制Handler用法總結(jié),希望對(duì)大家有所幫助。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Android利用ScaleTransition實(shí)現(xiàn)吹氣球動(dòng)畫(huà)
這篇文章主要為大家介紹了如何將利用ScaleTransition實(shí)現(xiàn)一個(gè)吹氣球的動(dòng)畫(huà),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2022-04-04
Android開(kāi)發(fā)Jetpack組件ViewModel與LiveData使用講解
Jetpack是一個(gè)由多個(gè)技術(shù)庫(kù)組成的套件,可幫助開(kāi)發(fā)者遵循最佳做法,減少樣板代碼并編寫(xiě)可在各種Android版本和設(shè)備中一致運(yùn)行的代碼,讓開(kāi)發(fā)者精力集中編寫(xiě)重要的代碼2022-09-09
深入淺析Android手機(jī)衛(wèi)士保存密碼時(shí)進(jìn)行md5加密
一般的手機(jī)沒(méi)有root權(quán)限,進(jìn)不去data/data目錄,當(dāng)手機(jī)刷機(jī)了后,擁有root權(quán)限,就可以進(jìn)入data/data目錄,查看我們保存的密碼文件,因此我們需要對(duì)存入的密碼進(jìn)行MD5加密,接下來(lái)通過(guò)本文給大家介紹Android手機(jī)衛(wèi)士保存密碼時(shí)進(jìn)行md5加密,需要的朋友一起學(xué)習(xí)吧2016-04-04
android實(shí)現(xiàn)手機(jī)傳感器調(diào)用
這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)手機(jī)傳感器調(diào)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04
Android App開(kāi)發(fā)中將View或Drawable轉(zhuǎn)為Bitmap的方法
這篇文章主要介紹了Android App開(kāi)發(fā)中將View或Drawable轉(zhuǎn)為Bitmap的方法,其中View轉(zhuǎn)換時(shí)作者特別提到了getDrawingCache=null問(wèn)題的解決方法,需要的朋友可以參考下2016-03-03
Android編程應(yīng)用風(fēng)格和主題詳解
這篇文章主要介紹了Android編程應(yīng)用風(fēng)格和主題,較為詳細(xì)的分析了Android應(yīng)用風(fēng)格和主題的概念、功能、使用方法與注意事項(xiàng),需要的朋友可以參考下2016-10-10
android 獲取手機(jī)GSM/CDMA信號(hào)信息,并獲得基站信息的方法
下面小編就為大家?guī)?lái)一篇android 獲取手機(jī)GSM/CDMA信號(hào)信息,并獲得基站信息的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-11-11

