訊息傳遞機制之Handler機制

2021-08-15 20:37:34 字數 4332 閱讀 4210

在專案中, 都會遇見執行緒之間通訊, 元件之間通訊.

在應用程式中,往往會有一些比較耗時的操作 , 為了防止阻塞主線程 , 會將耗時的操作放到子執行緒中執行 , 處理完成後再去更新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語句進行匹配處理...