【移動應用開發(fā)技術】Android編程實現(xiàn)異步消息處理機制的幾種方法總結_第1頁
【移動應用開發(fā)技術】Android編程實現(xiàn)異步消息處理機制的幾種方法總結_第2頁
【移動應用開發(fā)技術】Android編程實現(xiàn)異步消息處理機制的幾種方法總結_第3頁
【移動應用開發(fā)技術】Android編程實現(xiàn)異步消息處理機制的幾種方法總結_第4頁
【移動應用開發(fā)技術】Android編程實現(xiàn)異步消息處理機制的幾種方法總結_第5頁
免費預覽已結束,剩余1頁可下載查看

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

【移動應用開發(fā)技術】Android編程實現(xiàn)異步消息處理機制的幾種方法總結

本文實例講述了Android編程實現(xiàn)異步消息處理機制的幾種方法。分享給大家供大家參考,具體如下:1、概述Android需要更新ui的話就必須在ui線程上進行操作。否則就會拋異常。假如有耗時操作,比如:在子線程中下載文件,通知ui線程下載進度,ui線程去更新進度等,這個時候我們就需要用到異步消息處理。一、什么是HandlerHandler是Android提供用來異步更新UI的一套機制,也是一套消息處理機制,可以用它來發(fā)送消息,也可以用它來接收消息。二、為什么使用HandlerAndroid在設計之時,就封裝了一套消息的創(chuàng)建、傳遞、處理機制,作為系統(tǒng)原生的異步消息處理機制的實現(xiàn)之一,我們需要遵循這樣的處理機制,該機制的另外一種實現(xiàn)是AsyncTask。三、Handler用法1、postdelayed()延時發(fā)送執(zhí)行子線程(Demo)

2、sendMessage()回調(diào)handleMessage()傳遞消息

3、sendToTarget()傳遞消息四、為什么在Android中只能通過Handler機制在主線程中更新UI?最根本的是解決多線程并發(fā)問題。

假如在同一個Activity中,有多個線程同時更新UI,且沒有加鎖,那會導致什么問題呢?

UI更新混亂。

假如加鎖呢?

會導致性能下降。

使用Handler機制,我們不用去考慮多線程的問題,所有更新UI的操作,都是在主線程消息隊列中輪詢?nèi)ヌ幚淼摹?/p>

Handler、Looper、Message這三者都與Android異步消息處理線程相關的概念。那么什么叫異步消息處理線程呢?

異步消息處理線程啟動后會進入一個無限的循環(huán)體之中,每循環(huán)一次,從其內(nèi)部的消息隊列中取出一個消息,然后回調(diào)相應的消息處理函數(shù),執(zhí)行完成一個消息后則繼續(xù)循環(huán)。若消息隊列為空,線程則會阻塞等待。

—此處有圖為證。源碼解析1、Looper對于Looper主要是prepare()和loop()兩個方法。sThreadLocal是一個ThreadLocal對象,可以在一個線程中存儲變量。在第5行,將一個Looper的實例放入了ThreadLocal,并且2-4行判斷了sThreadLocal是否為null,否則拋出異常。這也就說明了Looper.prepare()方法不能被調(diào)用兩次,同時也保證了一個線程中只有一個Looper實例~在構造方法中,創(chuàng)建了一個MessageQueue(消息隊列)。第2行:方法直接返回了sThreadLocal存儲的Looper實例,如果me為null則拋出異常,也就是說loop方法必須在prepare方法之后執(zhí)行。

第6行:拿到該looper實例中的mQueue(消息隊列)

13到45行:就進入了我們所說的無限循環(huán)。

14行:取出一條消息,如果沒有消息則阻塞。

27行:使用調(diào)用msg.target.dispatchMessage(msg);把消息交給msg的target的dispatchMessage方法去處理。Msg的target是什么呢?其實就是handler對象,下面會進行分析。

44行:釋放消息占據(jù)的資源。Looper主要作用:1、與當前線程綁定,保證一個線程只會有一個Looper實例,同時一個Looper實例也只有一個MessageQueue。

2、loop()方法,不斷從MessageQueue中去取消息,交給消息的target屬性的dispatchMessage去處理。好了,我們的異步消息處理線程已經(jīng)有了消息隊列(MessageQueue),也有了在無限循環(huán)體中取出消息的哥們,現(xiàn)在缺的就是發(fā)送消息的對象了,于是乎:Handler登場了。2、Handler使用Handler之前,我們都是初始化一個實例,比如用于更新UI線程,我們會在聲明的時候直接初始化,或者在onCreate中初始化Handler實例。所以我們首先看Handler的構造方法,看其如何與MessageQueue聯(lián)系上的,它在子線程中發(fā)送的消息(一般發(fā)送消息都在非UI線程)怎么發(fā)送到MessageQueue中的。14行:通過Looper.myLooper()獲取了當前線程保存的Looper實例,然后在19行又獲取了這個Looper實例中保存的MessageQueue(消息隊列),這樣就保證了handler的實例與我們Looper實例中MessageQueue關聯(lián)上了。輾轉(zhuǎn)反則最后調(diào)用了sendMessageAtTime方法。enqueueMessage中首先為msg.target賦值為this,【如果大家還記得Looper的loop方法會取出每個msg然后交給msg,target.dispatchMessage(msg)去處理消息】,也就是把當前的handler作為msg的target屬性。最終會調(diào)用queue的enqueueMessage的方法,也就是說handler發(fā)出的消息,最終會保存到消息隊列中去??梢钥吹?,第10行,調(diào)用了handleMessage方法,下面我們?nèi)タ催@個方法:可以看到這是一個空方法,為什么呢,因為消息的最終回調(diào)是由我們控制的,我們在創(chuàng)建handler的時候都是復寫handleMessage方法,然后根據(jù)msg.what進行消息處理。3、Handlerpostpost方法:getPostMessage方法:可以看到,在getPostMessage中,得到了一個Message對象,然后將我們創(chuàng)建的Runable對象作為callback屬性,賦值給了此message.

注:產(chǎn)生一個Message對象,可以new,也可以使用Message.obtain()方法;兩者都可以,但是更建議使用obtain方法,因為Message內(nèi)部維護了一個Message池用于Message的復用,避免使用new重新分配內(nèi)存。

sendMessageDelayed方法和handler.sendMessage方法最終調(diào)用的都是:可以看到,這里msg的callback和target都有值,那么會執(zhí)行哪個呢?

看dispatchMessage方法就能看出來。第2行,如果不為null,則執(zhí)行callback回調(diào),也就是我們的Runnable對象。

mCallback的值是如何賦值的,可以查看Handler的構造方法,默認mCallback的值為Null到此,這個流程已經(jīng)解釋完畢,總結一下在Activity中,我們并沒有顯示的調(diào)用Looper.prepare()和Looper.loop()方法,為啥Handler可以成功創(chuàng)建呢,這是因為在Activity的啟動代碼中,已經(jīng)在當前UI線程調(diào)用了Looper.prepare()和Looper.loop()方法。4、擴展其實Handler不僅可以更新UI,你完全可以在一個子線程中去創(chuàng)建一個Handler,然后使用這個handler實例在任何其他線程中發(fā)送消息,最終處理消息的代碼都會在你創(chuàng)建Handler實例的線程中運行。代碼:四種更新UI的方法1、Handler.post();

2、Handler.sendMessage();

3、runOnUIThread()

4、View.post()查看runOnUIThread()的源代碼(Activity中)

RunsthespecifiedactionontheUIthread.IfthecurrentthreadistheUIthread,thentheactionisexecutedimmediately.IfthecurrentthreadisnottheUIthread,theactionispostedtotheeventqueueoftheUIthread.

Parameters:

actiontheactiontorunontheUIthread

publicfinalvoid

runOnUiThread(Runnableaction){

if(Thread.currentThread()!=mUiThread){

mHandler.post(action);

}else{

action.run();

}

}

RunsthespecifiedactionontheUIthread.IfthecurrentthreadistheUIthread,thentheactionisexecutedimmediately.IfthecurrentthreadisnottheUIthread,theactionispostedtotheeventqueueoftheUIthread.

Parameters:

actiontheactiontorunontheUIthread

publicfinalvoid

runOnUiThread(Runnableaction){

if(Thread.currentThread()!=mUiThread){

mHandler.post(action);

}else{

action.run();

}

}補充:1.異步消息處理機制的另一種實現(xiàn):AsyncTask:主要方法:在onPreExecute()方法執(zhí)行完后,會馬上執(zhí)行這個方法,這個方法就是來處理異步任務的方法,Android操作系統(tǒng)會在后臺的線程池當中開啟一個worker

thread來執(zhí)行這個方法(即在workerthread當中執(zhí)行),執(zhí)行完后將執(zhí)行結果發(fā)送給最后一個onPostExecute

方法,在這個方法里,我們可以從網(wǎng)絡當中獲取數(shù)據(jù)等一些耗時的操作Thread當中執(zhí)行的,在異步任務執(zhí)行的時候,有時需要將執(zhí)行的進度返回給UI界面,例如下載一張網(wǎng)絡圖片,我們需要時刻顯示其下載的進度,就可以使用這個方法來更新進度。這個方法在調(diào)用之前,我們需要在

doInBackground方法中調(diào)用一個publishProgress(Progress)的方法來將進度時時刻刻傳遞給

onProgressUpdate方

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論