異步消息處理機(jī)制
主線程又被稱為UI線程袁辈,Android是不允許在子線程中進(jìn)行UI操作的恢口。在主線程中進(jìn)行耗時操作隙弛,程序易發(fā)生ANR錯誤(Application Not Response)拂到。我們必須在子線程中執(zhí)行一些耗時操作归榕,然后根據(jù)任務(wù)的執(zhí)行結(jié)果來更新相應(yīng)的UI控件叁征,這就用到了異步消息處理機(jī)制纳账。
代碼實現(xiàn):
public class MainActivity extends Activity {
private static final int IMAGE = 0;
private static final int TOAST = 1;
static ImageView iv ;
static MainActivity ma;
//Handler對象設(shè)置成static,內(nèi)部變量都需要是靜態(tài)static
static Handler handler = new Handler(){
//此方法在主線程中調(diào)用捺疼,可以用來刷新UI
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case IMAGE:
//把位圖對象顯示至ImageView
iv.setImageBitmap((Bitmap) msg.obj);
break;
case TOAST:
Toast.makeText(ma, "請求失敗", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
ma = this;
}
/**
* 下載圖片
*/
public void click(View v){
//創(chuàng)建一個子線程疏虫,在子線程中處理網(wǎng)絡(luò)請求
new Thread(){
@Override
public void run() {
//確定網(wǎng)址
String path = "http://192.168.1.100:8080/home_gradient.jpg";
try {
//將網(wǎng)址封裝成一個Url對象
URL url = new URL(path);
//獲取客戶端和服務(wù)器的連接對象,此時還沒有建立連接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//對連接對象進(jìn)行初始化
connection.setRequestMethod("GET"); //設(shè)置請求方法
connection.setConnectTimeout(5000); //設(shè)置連接超時
//發(fā)送請求啤呼,與服務(wù)器建立連接
connection.connect();
if (connection.getResponseCode() == 200) { //如果響應(yīng)嗎為200卧秘,說明請求成功
//獲取服務(wù)器中響應(yīng)頭中的流,流里的數(shù)據(jù)就是客戶端請求的數(shù)據(jù)
InputStream is = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(is);
//使用Handler對象的obtainMessage方法獲取一個消息對象Message
Message message = handler.obtainMessage();
//消息對象可以攜帶數(shù)據(jù)
message.obj = bitmap;
message.what = IMAGE;
//把消息發(fā)送至主線程的消息隊列
handler.sendMessage(message);
}
else {
//彈出吐司也是一種UI的刷新官扣,需要在主線程中運(yùn)行
Message message = handler.obtainMessage();
message.what = TOAST;
handler.sendMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(connection != null){
//關(guān)閉HTTP連接
connection.disconnect();
}
}
}
}.start(); //開啟線程任務(wù)
}
}
解析異步消息處理機(jī)制
異步消息處理主要由四部分組成:Message
翅敌、Handler
、MessageQueue
和Looper
**Message: **
Message
對象是在線程之間傳遞的消息惕蹄,它可以在內(nèi)部攜帶少量的信息蚯涮,用于在不同的線程之間交換數(shù)據(jù)。what
卖陵、arg1
遭顶、arg2
字段攜帶一些整型數(shù)據(jù),obj
字段攜帶一個object
對象Handler:
Handler
對象主要用于發(fā)送和處理消息泪蔫。發(fā)送消息一般是使用sendMessage()
方法棒旗,消息被發(fā)送到消息隊列(MessageQueue)中,輪詢器(Looper)會把消息對象傳遞給消息處理器(Handler)撩荣,消息處理器調(diào)用handleMessage()
方法铣揉,此方法運(yùn)行在主線程中饶深,可以刷新UIMessageQueue:
MessageQueue
對象是消息隊列的意思,主要存放所有通過Handler
發(fā)送的消息逛拱。這部分消息會一直存放在消息隊列里粥喜,直至被輪詢器取出傳遞給消息處理器。每個線程中只會有一個消息隊列對象Looper:
Looper
是輪詢器的意思橘券,是每個線程中的消息隊列MessageQueue
的管家,其會不停的檢測消息隊列中是否有消息對象卿吐,若有將從消息隊列中取出消息對象傳遞給消息處理器