編輯:關於android開發
1. Handler消息傳遞機制初步認識:什麼是Handler?
handler通俗一點講就是用來在各個線程之間發送數據的處理對象。在任何線程中,只要獲得了另一個線程的handler,則可以通過 handler.sendMessage(message)方法向那個線程發送數據。基於這個機制,我們在處理多線程的時候可以新建一個thread,這個thread擁有UI線程中的一個handler。當thread處理完一些耗時的操作後通過傳遞過來的handler向UI線程發送數據,由UI線程去更新界面。
主線程:運行所有UI組件,它通過一個消息隊列來完成此任務。設備會將用戶
的每項操作轉換為消息,並將它們放入正在運行的消息隊列中。主線程位於一個循環中,並處理每條消息。如果任何一個消息用時超過5秒,Android將拋出
ANR。所以一個任務用時超過5秒,應該在一個獨立線程中完成它,或者延遲處理它,當主線程空閒下來再返回來處理它。
2.常用類:(Handler、Looper、Message、MessageQueue)
Message:消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理。
Handler:處理者,負責Message的發送及處理。使用Handler時,需要實現
handleMessage(Message
msg)方法來對特定的Message進行處理,例如更新UI等。Handler類的主要作用:(有兩個主要作用)1)、在工作線程中發送消息;2)、在
主線程中獲w/取、並處理消息。
MessageQueue:消息隊列,用來存放Handler發送過來的消息,並按照FIFO規則執行。當然,存放Message並非實際意義的保存,而是將Message串聯起來的,等待Looper的抽取。
Looper:消息泵,不斷地從MessageQueue中抽取Message執行。因此,一個MessageQueue需要一個Looper。
3.Handler、Looper、Message、MessageQueue之間的關系:
【備注:】
Looper對象用來為一個線程開啟一個消息循環,從而操作MessageQueue;
默認情況下,Android創建的線程沒有開啟消息循環Looper,但是主線程例外。
系統自動為主線程創建Looper對象,開啟消息循環;
所以主線程中使用new來創建Handler對象。而子線程中不能直接new來創建Handler對象就會異常。
子線程中創建Handler對象,步驟如下:
Looper.prepare();
Handler handler = new Handler() {
//handlemessage(){}
}
Looper.loop();
4.Handler類中常用方法:
(1) handleMessage() 用在主線程中,構造Handler對象時,重寫handleMessage()方法。該方法根據工作線程返回的消息標識,來分別執行不同的操作。
(2) sendEmptyMessage() 用在工作線程中,發送空消息。
(3) sendMessage() 用在工作線程中,立即發送消息。
5.Message消息類中常用屬性:
(1) arg1 用來存放整型數據
(2) arg2 用來存放整型數據
(3) obj 用來存放Object數據
(4) what 用於指定用戶自定義的消息代碼,這樣便於主線程接收後,根據消息代碼不同而執行不同的相應操作。
上一下Demo的示例代碼:
private Handler handler = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text_main_info = (TextView) findViewById(R.id.text_main_info);
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading...");
image_main = (ImageView) findViewById(R.id.image_main);
// 主線程中的handler對象會處理工作線程中發送的Message。根據Message的不同編號進行相應的操作。
handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// 工作線程中要發送的信息全都被放到了Message對象中,也就是上面的參數msg中。要進行操作就要先取出msg中傳遞的數據。
switch (msg.what) {
case 0:
// 工作線程發送what為0的信息代表線程開啟了。主線程中相應的顯示一個進度對話框
pDialog.show();
break;
case 1:
// 工作線程發送what為1的信息代表要線程已經將需要的數據加載完畢。本案例中就需要將該數據獲取到,顯示到指定ImageView控件中即可。
image_main.setImageBitmap((Bitmap) msg.obj);
break;
case 2:
// 工作線程發送what為2的信息代表工作線程結束。本案例中,主線程只需要將進度對話框取消即可。
pDialog.dismiss();
break;
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
// 當工作線程剛開始啟動時,希望顯示進度對話框,此時讓handler發送一個空信息即可。
// 當發送這個信息後,主線程會回調handler對象中的handleMessage()方法。handleMessage()方法中
// 會根據message的what種類來執行不同的操作。
handler.sendEmptyMessage(0);
// 工作線程執行訪問網絡,加載網絡圖片的任務。
byte[] data = HttpClientHelper.loadByteFromURL(urlString);
// 工作線程將網絡訪問獲取的字節數組生成Bitmap位圖。
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0,
data.length);
// 工作線程將要發送給主線程的信息都放到一個Message信息對象中。
// 而Message對象的構建建議使用obtain()方法生成,而不建議用new來生成。
Message msgMessage = Message.obtain();
// 將需要傳遞到主線程的數據放到Message對象的obj屬性中,以便於傳遞到主線程。
msgMessage.obj = bitmap;
// Message對象的what屬性是為了區別信息種類,而方便主線程中根據這些類別做相應的操作。
msgMessage.what = 1;
// handler對象攜帶著Message中的數據返回到主線程
handler.sendMessage(msgMessage);
// handler再發出一個空信息,目的是告訴主線程工作線程的任務執行完畢。一般主線程會接收到這個消息後,
// 將進度對話框關閉
handler.sendEmptyMessage(2);
}
}).start();
}
Android提高21篇之六:BroadcastReceiver
前面分別討論了Activity和Service,這次就輪到BroastcastReceiver,B
Android端通過HttpURLConnection上傳文件到服務器
Android端通過HttpURLConnection上傳文件到服務器 Android端通過HttpURLConnection上傳文件到服務器 一:實現原理 最近在做An
Android合並兩個APP的具體做法(掌握)
Android合並兩個APP的具體做法(掌握) 有時候因公司需求,要求合並兩個APP 使用裡面的功能。 平台:Studio 小白鼠:二維碼掃描 和自己項目
Android Studio發布到Jcenter
Android Studio發布到Jcenter 1.前言 擁抱開源,熱愛開源,將我們認為不錯的代碼開源到gihtub,將我們的庫發布到jcenter\mevan等。 2