Handler作爲Android中舉足輕重的知識點,無論是在實際開發還是在面試中都經常會用到,並且在網上關於Handler的講解不勝枚舉,本人深知水平有限,因此僅在此做一下自己的小結,權當學習中的筆記。
之前寫過一篇有關Handler中基本方法使用的一篇文章http://blog.csdn.net/james_shu/article/details/53367035,本篇基於此,寫出一些其他的新內容。
Android中的異步消息處理主要由4個部分組成:Message、Handler、MessageQueue和Looper。其中,
Message:Message是在線程之間傳遞的消息,當我們在不同的線程中傳遞數據時,Handler將我們要傳遞的信息封裝到Message中然後進行傳遞。
Handler:Handler主要是用於發送消息,接受並處理消息。
MessageQueue:消息隊列,它主要用於存放Handler發送的消息。存放於消息隊列中的消息等待被處理,每一個線程中只會有一個MessageQueue對象。
Looper:Looper是每一個線程中的MessageQueue的管家,調用Looper的loop()方法之後就會進入到一個無限循環中,然後當發現MessageQueue中存在一條消息就會將其取出並將這條消息傳遞到Handler的handleMessage()方法,每一個線程中只會有一個Looper對象。
這裏應該提到的一點是:
主線程中默認初始化了Looper,因此我們可以在創建Handler之後直接發送消息和處理消息,其中處理消息一定是創建Handler所在的線程中處理消息,而發送消息就可以在不同的線程中發送消息。
當我們創建一個新的線程的時候(不在主線程時),此時我們如果需要在新線程中創建Handler作爲其他線程與所創建的當前線程的通信的橋樑時,我們需要首先創建Looper對象,然後創建Handler對象。
下面我們以計算指定區間的質數爲例來介紹在新線程中創建Handler的用法:
佈局文件:
<EditText
android:id="@+id/etNum"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:onClick="calculate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="點擊得到處理的結果"
/>
代碼:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
calThread=new CalThread();
calThread.start();
}
private void initView() {
etNum= (EditText) findViewById(R.id.etNum);//使用Handler將用戶在UI界面輸入的數值上限動態的傳遞給新啓動的線程
}
class CalThread extends Thread{
public Handler mHandler; //在新線程中創建Handler,作爲主線程與新線程的通信的橋樑
//在主線程中系統已經初始化了一個Looper對象,因此程序可以直接創建handler對象然後使用創建的Handler對象來發送消息和處理消息
//然而當自己創建一個新的線程的時候,爲了使用自己創建的Handler對象,此時就應該自己同時創建一個Looper對象,此時Handler的功能纔算是完整的
@Override
public void run() {
super.run();
Looper.prepare();
mHandler=new Handler(){
//定義處理消息的方法
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what==0x123){
int upper=msg.getData().getInt(UPPER_NUM);
List<Integer> nums=new ArrayList<Integer>();
//計算從二開始的質數
outer:
for (int i=2;i<=upper;i++){
for (int j=2;j<=Math.sqrt(i);j++){
if(i!=2&&i%j==0){
continue outer;
}
}
nums.add(i);
}
Toast.makeText(MainActivity.this,nums.toString(),Toast.LENGTH_SHORT).show();
}
}
};
Looper.loop();
}
}
public void calculate(View view){
Message msg=new Message();
msg.what=0x123;
Bundle bundle=new Bundle();
bundle.putInt(UPPER_NUM,Integer.parseInt(etNum.getText().toString()));
msg.setData(bundle);
calThread.mHandler.sendMessage(msg);
}