




下載本文檔
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
【移動應用開發(fā)技術】Android中如何實現異步消息機制
這篇文章給大家介紹Android中如何實現異步消息機制,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。Android中的異步消息機制分為四個部分:Message、Handler、MessageQueue和Looper。其中,Message是線程之間傳遞的消息,其what、arg1、arg2字段可以攜帶整型數據,obj字段可以攜帶一個Object對象。Handler是處理者,主要用于發(fā)送消息和處理消息。發(fā)送消息的方法是sendMessage;處理消息的方法是handleMessage(),Message字段攜帶的信息在該方法中用作判別。MessageQueue是消息隊列,存放所有Handler發(fā)送的消息。Looper是消息隊列的“管家”,將消息從消息隊列中一條條取出,并分派到Handler的handleMessage()方法中。異步消息處理的流程為:①首先,需要在主線程中創(chuàng)建一個Handler對象,并重寫handleMessage()方法。②當子線程處理完耗時操作,需要將處理結果反饋到UI中時,先創(chuàng)建一個Message對象,并讓其what字段攜帶一個int值,然后通過Handler對象發(fā)送出去。③之后該消息會被添加到MessageQueue中等待被處理,而Looper會一直嘗試從MessageQueue中取出待處理消息,最后分發(fā)回Handler對象中的handleMessage()方法中。由于Handler對象是在主線程中創(chuàng)建的,所以可以在handleMessage()方法中安心地進行UI操作。通過一個例子來驗證一下:活動MainActivity中有一個按鈕和一個TextView。TextView初始化顯示“HelloWorld!”,之后點擊按鈕,進行耗時操作;耗時操作結束后,TextView顯示“Nicetomeetyou”。根據以上的分析,我無比自然地寫出了以下代碼:package
com.shaking.androidthreadtest;
import
android.os.Handler;
import
android.os.Message;
import
android.support.v7.app.AppCompatActivity;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.Button;
import
android.widget.TextView;
public
class
MainActivity
extends
AppCompatActivity
implements
View.OnClickListener{
private
static
final
int
UPDATE_TEXT=1;
private
String
data;
private
TextView
textView;
private
Handler
handler=new
Handler(){
@Override
public
void
handleMessage(Message
msg)
{
switch
(msg.what){
case
UPDATE_TEXT:
textView.setText(data);
}
}
};
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Button
button=findViewById(R.id.button);
textView=findViewById(R.id.text_view);
button.setOnClickListener(this);
}
@Override
public
void
onClick(View
view)
{
new
Thread(new
Runnable()
{
@Override
public
void
run()
{
//假設此處進行了耗時操作,最終得到結果字符串data
data="Nice
to
meet
you";
Message
message=new
Message();
message.what=UPDATE_TEXT;
handler.sendMessage(message);
}
}).start();
}
}首先,這么寫,是肯定沒有錯誤的!程序也可以正常運行。但是IDE給出了警告:“ThisHandlerclassshouldbestaticorleaksmightoccur”。這個警告的意思是:我們使用Handler這個類時,應該將其聲明為靜態(tài),否則會導致內存泄露。那么,為什么會發(fā)生內存泄露呢?原因是:第一:當我們通過Handler對象的sendMessage()方法發(fā)送一個Message對象時,該Message對象持有對該Handler對象的引用(正是依靠這個引用,Looper在消息隊列中取出該Message對象后,才能準確地將該Message對象分派回該Handler對象?。?。第二,我們在主線程中創(chuàng)建Handler對象時,為了重寫其handleMessage()方法,使用了匿名內部類的方式來創(chuàng)建該Handler對象。而匿名內部類和非靜態(tài)內部類都是隱性地持有一個對外部類的引用!所以,該Handler對象持有外部類MainActivity的引用。以上兩個結合在一起,問題就來了:Message對象持有Handler對象引用,Handler對象持有MainActivity的引用。所以,MainActivity該活動永遠無法被內存回收,直到Message被回收為止!如果Message對象在子線程中被發(fā)送至消息隊列,然后一直沒有被處理,該活動所在的主線程也會一直掛著,而不會被內存回收。所以,會導致內存泄露。知道了原因,那么解決方法是什么?其實之前的警告,已經給出了解決方案。那就是通過靜態(tài)內部類的方式創(chuàng)建Handler對象,因為靜態(tài)內部類不會持有對外部類對象的引用。這時候,我又自然而然地創(chuàng)建一個靜態(tài)內部類,繼承自Handler類,然后重寫其handleMessage方法。private
static
class
MyHandler
extends
Handler{
@Override
public
void
handleMessage(Message
msg)
{
}
}但是,此處又出現了一個問題!如果我不持有對外部類的引用了,那么我怎么使用外部類的方法和對象?畢竟我是要在handleMessage()方法中進行UI操作的。對于這種使用了靜態(tài)內部類來避免內存泄露,同時又需要調用外部類的方法的情況:可以使用弱引用!即我們在該內部類中聲明一個對外部類對象的弱引用。這樣即可以調用外部類的方法,又不會導致內存泄露。具體修改后的代碼,如下:package
com.shaking.androidthreadtest;
import
android.os.Handler;
import
android.os.Message;
import
android.support.v7.app.AppCompatActivity;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.Button;
import
android.widget.TextView;
import
java.lang.ref.WeakReference;
public
class
MainActivity
extends
AppCompatActivity
implements
View.OnClickListener{
private
static
final
int
UPDATE_TEXT=1;
private
String
data;
private
TextView
textView;
private
static
class
MyHandler
extends
Handler{
//使該內部類持有對外部類的弱引用
private
WeakReference<MainActivity>
weakReference;
//構造器中完成弱引用初始化
MyHandler(MainActivity
activity){
weakReference=new
WeakReference<>(activity);
}
@Override
public
void
handleMessage(Message
msg)
{
//通過弱引用的get()方法獲得外部類對象的引用
MainActivity
activity=weakReference.get();
activity.textView.setText(activity.data);
}
}
//創(chuàng)建Handler對象
private
MyHandler
handler=new
MyHandler(this);
@Override
protected
void
onCreate(Bundle
savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
Button
button=findViewById(R.id.button);
textView=findViewById(R.id.text_view);
button.setOnClickListener(this);
}
@Override
public
void
onClick(View
view)
{
new
Thread(new
Runnable()
{
@Override
public
void
run()
{
//假設此處進行了耗時操作,最終得到結果
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 信托與綠色交通基礎設施建設考核試卷
- 體育競賽活動安保措施與實施細節(jié)考核試卷
- 印刷企業(yè)綠色印刷技術發(fā)展趨勢分析考核試卷
- 室內模擬賽車與駕駛模擬器設備出租考核試卷
- 整車制造的工藝技術創(chuàng)新考核試卷
- 家庭插花培訓課件
- 借款附加資產合同范本
- 購房合同范本年
- 勞務人工合同范本
- 樓層拆除工程合同范本
- 比較政治制度導論
- 農村土地承包調解仲裁與仲裁庭審技巧課件
- 介入放射學全套教程
- 人教版政治七年級下冊全套課件
- 口語教程4整套課件完整版教學教程最全電子講義教案
- 高壓氧艙課件
- 加德納多元智能測評量表【復制】
- 譯林英語四年級下冊4B各單元教學反思
- 國家電網有限公司十八項電網重大反事故措施(修訂版)
- 環(huán)氧乙烷固定床反應器課程設計
- 班、團、隊一體化建設實施方案
評論
0/150
提交評論