Android學(xué)習(xí)筆記線程Message和Runnable_第1頁(yè)
Android學(xué)習(xí)筆記線程Message和Runnable_第2頁(yè)
Android學(xué)習(xí)筆記線程Message和Runnable_第3頁(yè)
Android學(xué)習(xí)筆記線程Message和Runnable_第4頁(yè)
Android學(xué)習(xí)筆記線程Message和Runnable_第5頁(yè)
已閱讀5頁(yè),還剩3頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、An droid 學(xué)習(xí)筆記:線程:Message和 Ru nn able程序需要相應(yīng)用戶的操作,最要能在200ms (0.2s )之內(nèi),如果超過(guò)5秒沒(méi)有反應(yīng),ActivityManager會(huì)沒(méi)有提示就kill 了 activity。然而,activity可能真的需要時(shí)間來(lái)進(jìn)行處理,這往往會(huì)用到后臺(tái)線程-background thread 。后臺(tái)線程可以 安全地 和UI線程進(jìn)行交互, 其中后臺(tái)線程是不能修改UI的。我不太確切知曉“不能修改UI”到何種程度,例如在下面的 例子進(jìn)度條狀態(tài)的修改是允許的,在復(fù)雜的例子中可能會(huì)出現(xiàn)問(wèn)題,例如兩個(gè)后臺(tái)線程都要處理同一個(gè)widget,可能會(huì)有不可預(yù)知的情況出

2、現(xiàn),然而就編程而言,確實(shí)不應(yīng)當(dāng)如此處理,后 臺(tái)進(jìn)程應(yīng)避免涉 及UI的處理,UI的歸UI,處理的規(guī)處理。這樣才是良好的編程風(fēng)格或者是一 種編程原則。通過(guò)創(chuàng)建一個(gè)Handler子類(lèi)的對(duì)象,每個(gè)acvivity 只需一個(gè)Handler對(duì)象。后臺(tái)進(jìn)程可通過(guò)兩 種方式Handler進(jìn)行通 信:message和Runnable對(duì)象,其結(jié)果實(shí)質(zhì)都是將在 Handler的隊(duì)列 中放入內(nèi)容,message是放置信息,可以傳遞一些參 數(shù),Handler獲取這些信息并將判度如何 處理,而Runnable則是直接給出處理的方法。隊(duì)列就是依次執(zhí)行,Handler會(huì)處理完一個(gè)消息或者執(zhí) 行完某個(gè)處理在進(jìn)行下一步,這樣不會(huì)

3、出現(xiàn)多個(gè)線程同時(shí)要求進(jìn)行UI處理而引發(fā)的混亂現(xiàn)象。這些隊(duì)列中的內(nèi)容(無(wú)論 Message還是Runnable)可以要求馬上執(zhí)行,延遲一定時(shí)間執(zhí)行或者 指定某個(gè)時(shí)刻執(zhí)行,如果將他們放置在隊(duì)列頭,則表示具有最高有限級(jí)別,立即執(zhí)行。這些函數(shù)包括有:sendMessageO, sendMessageAtFrontOfQueue(), sendMessageAtTime(), sendMessageDelayed()以及用于在隊(duì)列中加入 Runnable 的 post(), postAtFrontOfQueue(), po stAtTimeO, po stDelay()。一般而言,推薦是Messge方式

4、,這樣程序設(shè)計(jì)得可以更為靈活,而 Runnable在某些簡(jiǎn)單明確 的方式中使用。我們將通過(guò)三種方法編寫(xiě)一個(gè)小例子來(lái)學(xué)習(xí)。這個(gè)例子是一個(gè)進(jìn)度條,每隔1秒,進(jìn)度條步進(jìn)5,如果acvity停止時(shí),進(jìn)度條歸零。An droid XML :<?xml version="1.0" encoding="utf-8"?> <LinearLayout/>vP rogressBar android:id="+id/c15_ progress" style="?android:attr/ progressBarStyleH

5、orizontal" android:layout_width="fill_ parent" android:layout_height="wrap_content" v/LinearLayout>/><!-這表明采用傳統(tǒng)水平進(jìn)度條的方式例子一:線程開(kāi)啟,采用 Message傳遞后臺(tái)線程和UI主線程之間的信息P ublic class Chap ter15Test1 extends Activity p rivate P rogressBar bar = null;p rivate boolean isRunning = fa

6、lse;'/*我們?yōu)檫@個(gè)Acivity 創(chuàng)建一個(gè)用于和后臺(tái)程序通信的handler,簡(jiǎn)單地,只要一收到 message,就將IIprogressbar 進(jìn)度增加 5。*/I1/* 步驟1:創(chuàng)建Handler,并通過(guò)handleMessage()給出當(dāng)收到消息是 UI需要進(jìn)行如何處理,例子簡(jiǎn)單I;不對(duì)msg的內(nèi)容進(jìn)行分析*/' Handler handler= new Handler()p ublic voidhandleMessage (Message msg) bar.increment ProgressBy(5);' p rotected void onCreate

7、(Bundle savedInstanceState) sup er.onCreate(savedlnstanceState);setContentView(R.layout.cha pter_15_test1);bar=(P rogressBar)findViewByld(R.id.c15_ progress);/*on Start 是UI初始化并顯示時(shí)調(diào)用*/ip rotected void onStart() sup er.onStart();bar.set Progress(O);/*步驟2:建立后臺(tái)線程處理,采用Thread,其中run()的內(nèi)容,就是線程并行處理的內(nèi)容,Thread

8、是 Runnable 的 implements*/Thread background = new Thread(new Runnable()p ublic voidrun() tryfor(int i = 0; i < 20 && isRunning; i +)IThread.slee p(1000);i/*步驟2.1 :發(fā)送Message到隊(duì)列中,參數(shù)中的 obtainMessage()是用于給出一個(gè)新Message,本例無(wú)參數(shù),對(duì)應(yīng)的在 handler在隊(duì)列中收到這條消息時(shí),則通過(guò) handleMessage()進(jìn)行處理!*/handler.sendMessage(h

9、andler. obtainMessage ();catch(Throwable t)/jest end the thread);isRunning = true;/*步驟3 :啟動(dòng)線程*/background.start();/*onStop是Ul停止顯示時(shí)調(diào)用,例如我們按了返回鍵*/ P rotected void onSt op() !sup er.onSt op();isRunning = false;!例子2:米用Runnable我們?cè)谏厦娴睦拥幕A(chǔ)上進(jìn)行修改,如下/*步驟1 :由于不需要處理 Message,也即不需要處理 handleMessage()*/I Handler h

10、andler= new Handler();/*步驟1.1 :定義處理動(dòng)作,采用 Runnable的實(shí)例,通過(guò)implements runii將進(jìn)度條步進(jìn)5。由于我們將在 Thread中使用這個(gè)實(shí)例,所以考慮采用final()來(lái)定制處理,這里是簡(jiǎn)單的方式*/final Runnable r =new Runnable() p ublic void run()bar.increment ProgressBy(5);對(duì)于 runnable 方式,采用 post在onStart()中的步驟2 :線程的處理,和提供 message不同,'*/Thread background = new Th

11、read(new Runnable()p ublic void run() tryfor(int i = 0; i < 20 && isRunning; i +)Thread.slee p(1000);handler. post(r);catch(Throwable t)/jest end the thread);background.start();例子3:可以用延遲處理實(shí)現(xiàn)定時(shí)觸發(fā),讓程序更為簡(jiǎn)單在這里例子,事實(shí)我們是進(jìn)行定時(shí)的處理,利用Handler隊(duì)列可以設(shè)置延期處理的方式,我們并不需要?jiǎng)?chuàng)建一個(gè)后臺(tái)運(yùn)行的線程,也可以實(shí)現(xiàn)Handler handler= new H

12、andler。;I 在onStart()I / 利用handler.postDelayed(r,1000),在隊(duì)列中要求延遲 1秒后進(jìn)行r的處理,而在r的處理中,最后在handler的隊(duì)列中加 入一個(gè)要求延遲1秒的處理,如是,就可以實(shí)現(xiàn)每隔1秒的定期處理。handler. postDelayed(new Runnable() p ublic void run() if(isRunning && Cha pter15Test2.step < 20)ste p +;bar.increment ProgressBy(5);handler. postDelayed(this, 1

13、000);,1000);在這個(gè)例子中,我們基礎(chǔ)某種判度,自動(dòng)停止向隊(duì)列加入處理。如果有某種情況, 我們需要清除隊(duì)列中的消息或者理,可以使用removMessagesO或者removeCallbacks()的處理,這種對(duì)于延遲處理方式是非常有用的,可以中斷定期 的處理。當(dāng)然,一般來(lái)講 我們希望能夠得到某種判度,以使得定期處理能夠優(yōu)雅 地結(jié)束,而不是簡(jiǎn)單地從隊(duì)列中將消息或者處理刪除。例子4:不知道在UI主線程還是在后臺(tái)線程有時(shí)候,我們并不清楚代碼將在 UI線程還是后臺(tái)線程運(yùn)行,例如這些代碼封裝為一個(gè)JAR提供給其他人調(diào)用,我們并不清楚其他人如何使用這些代碼。為了解決這個(gè)問(wèn)題An droid在act

14、ivity中提供了 runOnUiThread(),如果在UI線程,貝U馬上執(zhí)行,如果在后臺(tái)線程,則將Runnable的執(zhí)行內(nèi)容加入到后臺(tái)線程的隊(duì)列中,這樣無(wú)論代碼在UI線程還是后臺(tái)線程都能安全地執(zhí)行。我們?cè)诶?的基礎(chǔ)上進(jìn)行試驗(yàn):1、建立一個(gè)Runnable,以便我們將在UI和后臺(tái)Thread中進(jìn)行試驗(yàn)Runnable runAction = new Runnable(),因?yàn)槲覀儫o(wú)法確定 Runnable具體運(yùn)行的p ublic void run()'contextIIi Toast.makeText(/注意,我們不能使用 Toast.makeText(this,.)getA pp

15、 licationContext(),"Hello!",Toast.LENGTH_SHORT).show();/Log.d("WEI","runAction . is called");由于Toast的顯示和隱藏需要一定的時(shí)間,而間隔 1秒顯然不夠,我們將例子1的間隔時(shí)間1000ms改為5000ms這樣會(huì)比較清晰,當(dāng)然可以采用 Log.d的方式來(lái) 替代。2、在UI線程中執(zhí)行該操作,在后臺(tái)線程中增加該操作,這個(gè)操作無(wú)論是在UI還是在后臺(tái)線程都是可以正確執(zhí)行的。p rotected void onStart() ! Thread back

16、ground = new Thread(new Runnable()!p ublic void run() :tryIIifor(int i = 0; i < 20 && isRunning; i +)IIThread.slee p(5000);!ihandler.sendMessage(handler.obtainMessage();IIirunOnUiThread (runAction);II,catch (T hrowable t)Ij/jest end the threadIIII'i );I isRunning = true;'backgroun

17、d.start();runOnUiThread (runAction); ;例子 5: HandIerThread在上面的例子中,無(wú)論是否使用了后臺(tái)線程(例子 的處理,一般的使用方式為我們通過(guò)后臺(tái)線程執(zhí) 息或者處理方式到Handler的的隊(duì)列中,然手在1-2),Handler的處理實(shí)際就是UI主線程 行某些操作,如果需要進(jìn)行 UI的互動(dòng),將消 UI主線程中進(jìn)行處理。這是我們通用的情況。之前我們討論過(guò)為何UI的歸UI,處理的處理,然而,可能有這樣的需求,舉個(gè)例子,在某些 情況下,Handler收到消息觸發(fā)的處理中可能會(huì)有 Sleep(),這會(huì)導(dǎo)致main線程進(jìn)入sleep狀 態(tài),不是我們期待的。

18、因此我們希望通過(guò)一個(gè)線程專(zhuān)門(mén)處理Hanlder的消息,這個(gè)線程也是依次從Handler的隊(duì)列中獲取信息,逐個(gè)進(jìn)行處理,保證安全,不會(huì)出現(xiàn)混亂引發(fā)的異常。針對(duì)此An droid提供的Han dIerThread。方式使用方法如下:/步驟1 :創(chuàng)薪HandlerThread的一個(gè)對(duì)象,并開(kāi)啟這個(gè)線程,HandlerThread 將通過(guò)Loo per來(lái)處理Handler對(duì)來(lái)中的消息,也就是如果發(fā)現(xiàn)Handler中有消息,將在 HandlerThread這個(gè)線程中進(jìn)行處理。HandlerThread ht = new HandlerThread("hander_thread");I_1步驟2 :啟動(dòng)handerhandler 這個(gè)線程;iht.start();1步驟3 :創(chuàng)建handler中,帶上 Loo per的參數(shù),即handlerThr

溫馨提示

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

評(píng)論

0/150

提交評(píng)論