? ?最近幾天公司的項(xiàng)目迭代了一個(gè)版本张遭,閑來(lái)無(wú)事瞬项,想對(duì)一些基礎(chǔ)知識(shí)進(jìn)行回顧下岁经,靈光一現(xiàn)就想到了Handler機(jī)制朋沮,因?yàn)檫@個(gè)在android實(shí)際的開發(fā)過(guò)程中還是很常見(jiàn)的,有了它缀壤,我們可以在完成一個(gè)很長(zhǎng)時(shí)間的任務(wù)后做出相應(yīng)的通知樊拓,例如更新UI,接下來(lái)切入正題塘慕。
Handler 可以 和Looper 來(lái)滿足咱們線程間的通信筋夏。Handler先進(jìn)先出原則。而Looper類用來(lái)管理特定線程內(nèi)對(duì)象之間的消息交換图呢。
1条篷、在UI線程中可以產(chǎn)生一個(gè)Looper對(duì)象骗随,用Looper來(lái)管理此線程里的MessageQueue(消息隊(duì)列)。
2赴叹、在Handler中你可以構(gòu)造Handler對(duì)象來(lái)與Looper溝通鸿染,以便更新新的消息MessageQueue里;或者接收Looper從Message Queue取出所送來(lái)的消息。Message Queue就是用來(lái)存放線程放入的消息
3稚瘾、使用handler的同學(xué)都知道牡昆,當(dāng)咱們的UIthread隊(duì)列,如果處理一個(gè)消息超過(guò)5秒時(shí),android 就會(huì)拋出一個(gè) ANR(android程序無(wú)響應(yīng))的消息,So,我們需要把一些要處理比較長(zhǎng)的消息,在子線程中進(jìn)行處理,把處理后的結(jié)果,返回給主線程就可以了,來(lái)看看兩張關(guān)系圖(很經(jīng)典又直觀的圖)
4、理清楚原理來(lái)看看handler中常用的方法
①摊欠,更新一個(gè)組件的內(nèi)容
handler.post(new Runnable(){
@Override
public void run() {
//do something 寫更新UI
}});
② 可以創(chuàng)建多線程消息的方法
handler.postDelayed(runnable, 2000);//使用postDelayed方法后丢烘,2秒執(zhí)行runnable的操作
實(shí)際上也就實(shí)現(xiàn)了一個(gè)2s的一個(gè)定時(shí)器
handler.removeCallbacks(runnable);//這個(gè)可以關(guān)閉定時(shí)器
Handler handler =newHandler();
handler.postDelayed(newRunnable() {
@Override
public voidrun() {
//常見(jiàn)于啟動(dòng)界面的時(shí)候,有一個(gè)延時(shí)的加載
startActivity(newIntent(MainActivity.this,SecondActivity.class));/
MainActivity.this.finish();
}},2000);
③sendMessage(new Message) 指在Handler在發(fā)送消息的時(shí)候些椒,需要發(fā)送一個(gè)新的對(duì)象
class UpdateProgressBar Thread implements Runnable{
@Override
publicvoid run() {
int progress =0;
while( progress <= 100){
Message msg =new Message();
msg.arg1 = progress;
handler.sendMessage(msg);
progress += 10;
try{
Thread.sleep(1000);
}catch(InterruptedException e) {
e.printStackTrace();}}
Message msg = handler.obtainMessage();
msg.arg1 = -1;
handler.sendMessage(msg);}}
④播瞳、HandlerThread是一個(gè)帶有消息循環(huán)的線程,并且有自己的消息隊(duì)列免糕,能夠接受其他線程發(fā)送消息赢乓。使用方法Java代碼如下:
HandlerThread mHandlerThread=newHandlerThread("handlerThread");
mHandlerThread.start();//啟動(dòng)線程
Handler mHandler =newHandler(tt.getLooper());
mHandler.postDelayed(newRunnable() {
@Override
publicvoidrun() {
Log.i("lukey","ThreadName:"+ Thread.currentThread().getName());
((HandlerThread)Thread.currentThread()).getLooper().quit();//關(guān)閉消息循環(huán),退出線程
}},1000);
5石窑、Message作為handler接受的對(duì)象,我們有必要知道Message這個(gè)數(shù)據(jù)類型是個(gè)怎樣的數(shù)據(jù)類型,我們來(lái)看看message 關(guān)于數(shù)據(jù)的字段
public int what
public int arg1
public int arg2
public Object obj
message 提供了一個(gè)對(duì)象來(lái)存儲(chǔ)對(duì)象,而且,還提供了三個(gè)int字段用來(lái)存儲(chǔ)少量int類型牌芋,除了以上三個(gè)Message自有的字段外,咱們還可以通過(guò)setData(Bundle b),來(lái)存儲(chǔ)一個(gè)Bundle對(duì)象,來(lái)存儲(chǔ)更豐富的數(shù)據(jù)類型和圖片.在初始化我們的message的時(shí)候就可以為我們的Message默認(rèn)字段賦值
Message msg = obtainMessage();
//按照順序設(shè)置我們what 字段的初值
Message msg = mHandler.obtainMessage(int what);
Message msg = mHandler.obtainMessage(int what,Object object);
Message msg = mHandler.obtainMessage(int what,int arg1,int arg2);
Message msg = mHandler.obtainMessage(int what,int arg1,int arg2, Object obj);