在專案中, 都會遇見執行緒之間通訊, 元件之間通訊.
在應用程式中,往往會有一些比較耗時的操作 , 為了防止阻塞主線程 , 會將耗時的操作放到子執行緒中執行 , 處理完成後再去更新ui , 但是android不允許子執行緒操作ui , 違背了android單執行緒模型的原則(即ui操作不是執行緒安全的而且這些操作必須放在ui執行緒中執行) , 因此android通過hander訊息機制來實現執行緒之間的通訊.
message: 訊息. 訊息處理物件以及資料等, 由messagequeue統一列隊 , 終由handler處理
handler : 處理者. 負責message的傳送及處理 . 使用handler時 , 需要實現handlemessage方法
messagequeue : 訊息佇列. 用來存放handler傳送過來的訊息 , 按照鍊錶的方式串聯起來 , 等待looper的抽取
looper : 輪詢器 . 不斷的從messagequeue中獲取message並執行 .
message物件建立
message msg = new message();
message msg = message.obtain();
在handler物件中 , 初始化了兩個物件 : looper , messagequeue . 初始化完成後 , 主線程的中looper物件已經開始輪詢迴圈的獲取訊息 , 如果沒有訊息 , 主線程就會處於休眠狀態.
public handler()
// 主線程的訊息佇列物件
mqueue = mlooper.mqueue;
mcallback = callback;
masynchronous = async;
}
主線程looper的初始化 , 在activitythread中的main函式中:
public static void main(string args)
...
trace.traceend(trace.trace_tag_activity_manager);
//開啟迴圈,looper進入乙個死迴圈中不停的取出訊息並處理,一旦looper停止,那麼我們的應用也就結束
looper.loop();
//looper停止的話就會走到這裡丟擲異常
throw new runtimeexception("main thread loop unexpectedly exited");
}
looper類中的loop方法 ,是乙個死迴圈, 它會不停的獲取message訊息 , 交給handler處理 , 如果沒有訊息messagequeue就會阻塞
public static final void loop()
}
handler物件傳送訊息 , sendmessage方法:
public final boolean sendmessage(message msg)
public final boolean sendmessagedelayed(message msg, long delaymillis)
return sendmessageattime(msg, systemclock.uptimemillis() + delaymillis);
}public boolean sendmessageattime(message msg, long uptimemillis) else
return sent;
}// 此方法是把傳遞進來的訊息按照先後順序或者時間來進行排序, 並且存起來.
final boolean enqueuemessage(message msg, long when) else
msg.next = prev.next;
prev.next = msg;
needwake = false; // still waiting on head, no need to wake up
}...
}
當主線程被喚醒 , 會繼續執行while迴圈 , 去訊息佇列messagequeue中獲取訊息
public static final void loop()
if (me.mlogging!= null) me.mlogging.println(
">>>>> dispatching to " + msg.target + " "
+ msg.callback + ": " + msg.what
);// 因為message中的target物件就是handler物件, 這裡其實呼叫的是handler中的 dispatchmessage方法.
msg.target.dispatchmessage(msg);
if (me.mlogging!= null) me.mlogging.println(
"<<<<< finished to " + msg.target + " "
+ msg.callback);
msg.recycle();}}
}
handler中的dispatchmessage方法
public void dispatchmessage(message msg) else
}// 呼叫了自己的handlemessage方法.
handlemessage(msg);}}
1.傳送訊息
在主線程中定義handler
handler mhandler = new handler()}};
子執行緒傳送訊息,通知handler更新ui
private void getdatafromnet()
}.start();
}
sendemptymessage(int)
sendmessage(message)
obtainmessage(what,obj).sendtotarget()
sendmessageattime(message , long) //在指定時間傳送訊息
sendmessagedelayed(message, long) //延時傳送訊息
2. 執行任務
主線程中定義handler
handler mhandler = new handler();
子執行緒中提交任務更新ui
new thread()
});}
}.start();
注意: mhandler.post(runable)其實不會新起執行緒, 只是執行runable中的run()方法, 卻沒有執行start()方法, 所以runabel執行的ui執行緒
執行任務的方法
post(runnable)
postattime(runnable , long) 在未來的時間點執行任務
postdelayed(runnable,long) 延時ms執行任務
1.runonuithread(runable)
new thread(new runnable()
});}
}).start();
activity.runonuithread(runnable)將更新ui的**放在runnable中 , 然後需要更新ui時 . 再將runnable物件傳給activity.runonuithread(runable)
2.view.post(runnable)
new thread(new runnable()
});}
}).start();
3.asynctask代替thread
private void getdatafromnet()
private class mytask extends asynctask
//後台執行緒執行結束後的操作,其中引數result為doinbackground返回的結果
@override
protected void onpostexecute(object result)
}
以上是本人對於handler機制的一些理解和看法 , 如果有不對的地方 , 歡迎各位同仁指正. Handler訊息傳遞機制
使用方法 1.若在ui主線程中,則系統已經初始化了乙個looper物件 因為主線程也是乙個訊息迴圈,因此具有乙個looper,主線程的所有工作都是由其looper完成的looper不斷從訊息佇列中抓取訊息,然後完成訊息指定的任務 否則要自己建立乙個looper物件並啟動。我們無法通過構造器建立loo...
Handler訊息傳遞機制
android中ui並不是執行緒安全的,什麼是執行緒安全呢 這是維基給出的解釋。如果有多個執行緒操作ui,會造成執行緒不安全問題。因此android有規定 ui元件只能在activity中對ui進行操作。當乙個程式第一次啟動時,android會同時啟動乙個main thread 主線程 主要負責與u...
Android中Handler訊息傳遞機制
因為是在專案中的收穫,所以不全,以後遇到其他的我會加上。安卓中用handler機制來實現主線程和子執行緒之間的通訊,通訊的媒介是message的例項。首先要在主線程宣告乙個handler物件,然後重寫裡面的handmessage message msg 方法,用switch case語句進行匹配處理...