- 相關(guān)推薦
Android環(huán)境下主UI線(xiàn)程與子線(xiàn)程通信機制研究論文
1問(wèn)題的引出
如果需要用手機從網(wǎng)絡(luò )上下載一個(gè)圖片到自己的手機上,在onCreate方法中可以如下圖1所示的代碼。通過(guò)代碼會(huì )獲取并顯示所需要的位圖。但其中隱藏著(zhù)一個(gè)非常危險的問(wèn)題——代碼本身就是運行在主線(xiàn)程上。Android系統只能運行一個(gè)主線(xiàn)程,而且只有主線(xiàn)程能夠與屏幕之間進(jìn)行任意權限級別的交互。這意味著(zhù),當代碼等待網(wǎng)絡(luò )回傳圖片數據的時(shí)候,任何內容都無(wú)法顯示到屏幕上。這段獲取圖片的代碼會(huì )限制在手機上任意地方執行任意操作。所以如果主線(xiàn)程被綁架,那么它在被釋放之前,系統就不會(huì )響應按單擊事件,不能接電話(huà),屏幕上不能顯示任何內容。這對于手機用戶(hù)來(lái)說(shuō)是災難性的。
2什么是子線(xiàn)程
為了有效解決手機被綁架的問(wèn)題,提高用戶(hù)體驗,提出了子線(xiàn)程。在A(yíng)ndroid的布局界面中,可以實(shí)現按鈕的單擊、TextView內容的修改,所有這些與界面控件相關(guān)的操作,實(shí)際上都是由主UI線(xiàn)程在負責運行。但有時(shí)候,程序會(huì )執行一些耗時(shí)的操作,比如復雜的計算、訪(fǎng)問(wèn)網(wǎng)絡(luò ),下載數據,查詢(xún)數據庫、甚至包括讓線(xiàn)程休眠等,這些操作如果放到主UI線(xiàn)程中執行,會(huì )造成主UI線(xiàn)程無(wú)法及時(shí)響應用戶(hù)在界面上的操作,造成界面假死的狀態(tài)。一般的解決方案是將耗時(shí)的操作交給另外一個(gè)子線(xiàn)程來(lái)執行,從而保證主UI線(xiàn)程的暢通。有時(shí)候子線(xiàn)程在完成了一部分的耗時(shí)操作以后,希望能夠在主界面上有所體現,此時(shí)子線(xiàn)程是不能夠直接操作界面控件的,它必須通過(guò)消息的方式告知主UI線(xiàn)程進(jìn)行控件更新。
3子線(xiàn)程與主UI線(xiàn)程的通信原理
Android應用程序運行時(shí),一個(gè)主線(xiàn)程被創(chuàng )建(也稱(chēng)作UI線(xiàn)程),此線(xiàn)程主要負責處理UI相關(guān)的事件,由于A(yíng)ndroid采用UI單線(xiàn)程模型,所以只能在主線(xiàn)程中對UI元素進(jìn)行操作,如果在非UI線(xiàn)程直接對UI進(jìn)行了操作,則會(huì )報錯,另外,對于運算量較大的操作和IO操作,我們需要新開(kāi)線(xiàn)程來(lái)處理這些工作,以免阻塞UI線(xiàn)程,子線(xiàn)程與主線(xiàn)程之間通信原理如下圖2所示。
從上圖2可以看出,要完成子線(xiàn)程與主UI線(xiàn)程之間的通信,需要配合多個(gè)類(lèi)來(lái)完成。其中Thread類(lèi)負責線(xiàn)程工作,要創(chuàng )建該類(lèi)需要實(shí)現Runnable接口的run()方法,run()方法中一般是耗時(shí)操作的代碼。第二個(gè)類(lèi)是Message類(lèi),用來(lái)描述消息,在Message對象中可以存儲一些信息。第三個(gè)類(lèi)是Handler類(lèi),用來(lái)發(fā)送和接受消息,要創(chuàng )建該類(lèi)需要實(shí)現handleMessage(Messagemsg)方法,該方法會(huì )在Handler對象接收到消息時(shí)被調用。那么這三個(gè)類(lèi)之間協(xié)同合作,才能有序地完成子線(xiàn)程與主UI線(xiàn)程之間的通信。
3.1Thread類(lèi)
要創(chuàng )建子線(xiàn)程對象,就需要使用Thread類(lèi)。要創(chuàng )建該類(lèi)需要實(shí)現Runnable接口的抽象方法run(),在run()方法中需要添加子線(xiàn)程所要運行任務(wù)的代碼。其次,Sleep(longtime)方法是讓線(xiàn)程休眠,其中time為休眠的時(shí)間,單位時(shí)毫秒。最后一定要用start()方法運行線(xiàn)程。之后該子線(xiàn)程就可以開(kāi)始工作了。
子線(xiàn)程在特定情況下需要通過(guò)Handler發(fā)送Message給主UI線(xiàn)程,委托主UI線(xiàn)程進(jìn)行一些與界面相關(guān)的處理,所以,發(fā)送消息的Handler類(lèi)也是其中的一個(gè)很重要的類(lèi)。
3.2Message類(lèi)
Message類(lèi)型的消息中包含了一個(gè)int類(lèi)型的成員對象what,利用what可以區分不同的消息類(lèi)型。返回值有兩種情況,如果消息成功放置到消息隊列則返回true,否則返回false。
3.3Handler類(lèi)
發(fā)送消息:所使用的類(lèi)為Handler類(lèi),方法為publicbooleansendMessage(Messagemsg),其中,msg是消息對象。Message類(lèi)型的消息中包含了一個(gè)int類(lèi)型的成員對象what,利用what可以區分不同的消息類(lèi)型。子線(xiàn)程將消息發(fā)送給主線(xiàn)程,主線(xiàn)程收到消息之后,會(huì )根據傳過(guò)來(lái)的消息信號的不同做不同的動(dòng)作。如果消息號為STOP,則子線(xiàn)程結束消息的傳送,如果消息號為CONTINUE,則繼續傳送消息。當子線(xiàn)程的狀態(tài)發(fā)生變化,則在子線(xiàn)程中發(fā)出Message,通知更新UI。
接收處理消息:使用的是Handler類(lèi),方法為publicvoidhan
dleMessage(Messagemsg),通過(guò)判斷msg.what可以區分不同的消息類(lèi)型。根據不同的消息類(lèi)型,主UI線(xiàn)程會(huì )產(chǎn)生不同的動(dòng)作來(lái)響應子線(xiàn)程。
4子線(xiàn)程與主線(xiàn)程之間通信的實(shí)例
該程序的界面如圖3所示,界面中存在一個(gè)水平進(jìn)度條和一個(gè)大環(huán)形進(jìn)度條,以及一個(gè)TextView來(lái)顯示“界面加載中。。!。運行中:水平滾動(dòng)條每1秒前進(jìn)一格,當進(jìn)度條的進(jìn)度達到100%時(shí),TextView顯示“頁(yè)面加載完畢”。
分析:要完成這樣的任務(wù),需要讓程序循環(huán)性地休眠1s后,更新水平進(jìn)度條。但是如果讓主程序休眠,會(huì )導致界面假死狀態(tài),造成用戶(hù)使用感受的下降,如何解決?就用到了上面所提到的線(xiàn)程。實(shí)現過(guò)程代碼如下圖4所示。
5需要改善的幾個(gè)問(wèn)題
。1)設置線(xiàn)程的中斷標記,有效地控制線(xiàn)程的進(jìn)度。在Eclipse中創(chuàng )建Android項目,通過(guò)實(shí)現Runnable接口來(lái)創(chuàng )建線(xiàn)程、開(kāi)啟線(xiàn)程、讓線(xiàn)程休眠指定的時(shí)間,除此之外,還可以中斷線(xiàn)程。當需要中斷指定線(xiàn)程時(shí),可以使用Thread類(lèi)提供的interrupt()方法來(lái)實(shí)現。使用interrupt()方法可以向指定的線(xiàn)程發(fā)送一個(gè)中斷請求,此時(shí)可以使用一個(gè)boolean型的標記變量來(lái)記錄該線(xiàn)程的中斷狀態(tài),并通過(guò)該標記變量來(lái)控制循環(huán)的執行與停止。
。2)子線(xiàn)程開(kāi)啟消息循環(huán)。在A(yíng)ndorid中一個(gè)線(xiàn)程對應一個(gè)Looper對象,而一個(gè)Looper對象對應一個(gè)MessageQueue消息隊列,消息隊列里面用于存放消息。Looper對象用來(lái)為一個(gè)線(xiàn)程開(kāi)啟一個(gè)消息循環(huán),用來(lái)操作消息隊列。默認情況下,系統自動(dòng)為主線(xiàn)程開(kāi)啟消息循環(huán),新建子線(xiàn)程中則需要手動(dòng)開(kāi)啟,否則會(huì )拋出異常。
6結語(yǔ)
Android的應用程序的多線(xiàn)程編程為我們充分利用系統資源提供了便利,同時(shí)也為設計復雜UI和耗時(shí)操作提供了途徑,提升了手機用戶(hù)的使用體驗。在子線(xiàn)程與UI主線(xiàn)程通信過(guò)程中,用到了try{}catch{Exceptione}{}語(yǔ)句,這個(gè)語(yǔ)法是代碼異常處理的,如果沒(méi)有try的話(huà),出現異常會(huì )導致程序崩潰。而try則可以保證程序的正常運行下去,并且輸出為什么出錯,對程序的維護有很大的幫助。
另外在主線(xiàn)程上應該避免下列操作:與網(wǎng)絡(luò )相關(guān)的操作;需要對文件系統進(jìn)行讀寫(xiě)操作的任務(wù);任何種類(lèi)的繁重事務(wù)處理(如圖片或視頻修改);在等待某個(gè)事務(wù)完成時(shí)會(huì )阻礙線(xiàn)程執行的任務(wù)等等。因此,作為一般規律,如果不涉及對用戶(hù)界面的設置或修改,就不要放在主線(xiàn)程上。
參考文獻
[1]余永佳,趙佩華,等.Android應用開(kāi)發(fā)基礎[M].北京:機械工業(yè)出版社,2014.
[2]蓋索林.Android開(kāi)發(fā)入門(mén)指南(第二版)[M].北京:人民郵電出版社,2013.
【Android環(huán)境下主UI線(xiàn)程與子線(xiàn)程通信機制研究論文】相關(guān)文章:
論文:Linux進(jìn)程和線(xiàn)程的基礎與管理08-18
在Windows2000下用多線(xiàn)程實(shí)現1394串行總線(xiàn)通信10-02
單片機系統中的多任務(wù)多線(xiàn)程機制的實(shí)現09-18
多線(xiàn)程技術(shù)在邊緣檢測方面的應用10-06
PPLive通信機制與流量識別研究08-20
船舶物聯(lián)網(wǎng)遠程數據通信機制研究論文07-16
全媒體環(huán)境下新聞?wù)Z(yǔ)言研究論文07-01