執行緒間通訊的訊息機制的Message和Handler
Message是訊息機制的資訊載體,開發人員可以在Message物件中封裝資料,封裝資料的方式有:
1)setData(),在Message中封裝Bundle型別的資料,在接收方使用getData()獲取該Bundle物件。
2)arg1屬性,int型別,用於封裝int型別變數
3)arg2屬性,int型別,與arg1相似
4)what屬性,int型別,用於封裝int型別變數,表示訊息的識別符號
5)obj屬性,object型別,用於封裝任意型別的資料
Handler訊息的傳送者和處理者,常用方法有
1)public final boolean sendMessage(Message msg);
2)public void HandleMessage(Message msg);
使用訊息機制傳送處理訊息,
public class MainActivity extends Activity { private ImageView ivImage; private Button btnLoadImage; private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ivImage=(ImageView) findViewById(R.id.imageView1); handler=new InnerHandler(); } /** * 自定義Handler * @author Administrator */ public class InnerHandler extends Handler{ @Override public void handleMessage(Message msg) { //接收訊息 Bitmap bm=(Bitmap) msg.obj; ivImage.setImageBitmap(bm); } } /** * 點選按鈕,載入圖片 * @param v */ public void doLoadImage(View v){ new Thread(){ public void run() { //從網路中載入圖片,即耗時操作 Bitmap bm=loadImageFromNetwork(); //建立訊息 Message msg=new Message(); msg.obj=bm; //傳送訊息 handler.sendMessage(msg); }; }.start(); } /** * 模擬從網路中載入圖片 */ public Bitmap loadImageFromNetwork(){ Bitmap bm=null; //模擬網路延遲8秒 try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } return bm=BitmapFactory.decodeResource(getResources(), R.drawable.meituan); }
Message存在公有的無參的構造方法,所以可以用new Message()建立Message物件,但是這種做法並不推薦。因為很多時候,需要很頻繁的傳送訊息,很頻繁的建立物件,會導致較大的系統開銷。為了避免較多的Message物件建立和銷燬造成較大的系統開銷,系統使用Message Pool(訊息池)來控制和管理Message物件。
Message Pool的大小為10,即可存放10個Message物件,當需要Message物件時,直接從池中獲取即可,無需建立。獲取Message物件的方法:
1)Message類的obtain靜態方法;
2)Handler的obtainMessage方法;
兩個方法都是過載很多次,我們可以查詢文件,使用方法。
在使用Message時一般遵循以下規則:
1)儘量使用Message的obtain方法或Handler的obtainMessage方法獲取Message物件,而不使用構造方法建立物件。
2)嚴格區分Message物件的arg1,arg2,what屬性。what標識訊息型別,常使用常量表現其意義,而arg1,arg2則表示具體數字意義的資料。
3)可以根據具體情況,將需要封裝的資料設定為全域性變數,在子執行緒中可以直接更新,在主執行緒中直接獲取,而無需封裝。
4)儘量不要在Message中封裝大量的資料,能使用obj屬性封裝的,就不要使用setData()/getData方法,因為其效率更高。
根據以上內容,部分程式碼可以更改為
public class MainActivity extends Activity {
private ImageView ivImage;
private Button btnLoadImage;
private Handler handler;
private Bitmap bm;
protected static final int LOAD_IMAGE_COMPLETED = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivImage=(ImageView) findViewById(R.id.imageView1);
handler=new InnerHandler();
}
/**
* 自定義Handler
* @author Administrator
*/
public class InnerHandler extends Handler{
@Override
public void handleMessage(Message msg) {
if(msg.what==LOAD_IMAGE_COMPLETED){
ivImage.setImageBitmap(bm);
}
}
}
/**
* 點選按鈕,載入圖片
* @param v
*/
public void doLoadImage(View v){
new Thread(){
public void run() {
//從網路中載入圖片,即耗時操作
bm=loadImageFromNetwork();
Message msg=new Message();
·msg.what=LOAD_IMAGE_COMPLETED;
handler.sendMessage(msg);
};
}.start();
}
}
以上程式碼是定義Handler的子類,並重寫handleMessage方法以處理訊息。其實關於Handler處理訊息,我們也可以自定義類實現Handler.Callback介面,並將該介面的實現類物件作為new Handler(Callback callback)的引數以建立Handler物件
以上程式碼部分可以修改為:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ivImage=(ImageView) findViewById(R.id.imageView1);
//handler=new InnerHandler();
handler=new Handler(new InnerCallback());
}
public class InnerCallback implements Handler.Callback{
@Override
public boolean handleMessage(Message msg) {
if(msg.what==LOAD_IMAGE_COMPLETED){
ivImage.setImageBitmap(bm);
}
return false;
}
}