anroi后臺(tái)優(yōu)秀服務(wù)概述_第1頁(yè)
anroi后臺(tái)優(yōu)秀服務(wù)概述_第2頁(yè)
anroi后臺(tái)優(yōu)秀服務(wù)概述_第3頁(yè)
anroi后臺(tái)優(yōu)秀服務(wù)概述_第4頁(yè)
anroi后臺(tái)優(yōu)秀服務(wù)概述_第5頁(yè)
已閱讀5頁(yè),還剩161頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

付費(fèi)下載

下載本文檔

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

文檔簡(jiǎn)介

第7章后臺(tái)服務(wù)本章學(xué)習(xí)目標(biāo)了解Service的原理和用途掌握本地服務(wù)的管理方法掌握服務(wù)的隱式啟動(dòng)和顯式啟動(dòng)方法了解線程的啟動(dòng)、掛起和停止方法了解跨線程的界面更新方法掌握遠(yuǎn)程服務(wù)的綁定和調(diào)用方法了解AIDL語(yǔ)言的用途和語(yǔ)法

7.1

Service簡(jiǎn)介ServiceService是Android系統(tǒng)的服務(wù)組件,適用于開(kāi)發(fā)沒(méi)有用戶界面且長(zhǎng)時(shí)間在后臺(tái)運(yùn)行的應(yīng)用功能因?yàn)槭謾C(jī)硬件性能和屏幕尺寸的限制,通常Android系統(tǒng)僅允許一個(gè)應(yīng)用程序處于激活狀態(tài)并顯示在手機(jī)屏幕上,而暫停其他處于未激活狀態(tài)的程序因此,Android系統(tǒng)需要一種后臺(tái)服務(wù)機(jī)制,允許在沒(méi)有用戶界面的情況下,使程序能夠長(zhǎng)時(shí)間在后臺(tái)運(yùn)行,實(shí)現(xiàn)應(yīng)用程序的后臺(tái)服務(wù)功能,并能夠處理事件或數(shù)據(jù)更新7.1

Service簡(jiǎn)介ServiceAndroid系統(tǒng)提供的Service(服務(wù))組件,不直接與用戶進(jìn)行交互,能夠長(zhǎng)期在后臺(tái)運(yùn)行在實(shí)際應(yīng)用中,有很多應(yīng)用需要使用Service,經(jīng)常提到的例子就是MP3播放器,軟件需要在關(guān)閉播放器界面后,仍能夠保持音樂(lè)持續(xù)播放,這就需要在Service組件中實(shí)現(xiàn)音樂(lè)回放功能7.1

Service簡(jiǎn)介Service

Service適用于無(wú)需用戶干預(yù),且規(guī)則或長(zhǎng)期運(yùn)行的后臺(tái)功能首先,因?yàn)镾ervice沒(méi)有用戶界面,更加有利于降低系統(tǒng)資源的消耗,而且Service比Activity具有更高的優(yōu)先級(jí),因此在系統(tǒng)資源緊張時(shí),Service不會(huì)被Android系統(tǒng)優(yōu)先終止即使Service被系統(tǒng)終止,在系統(tǒng)資源恢復(fù)后Service也將自動(dòng)恢復(fù)運(yùn)行狀態(tài),因此可以認(rèn)為Service是在系統(tǒng)中永久運(yùn)行的組件Service除了可以實(shí)現(xiàn)后臺(tái)服務(wù)功能,還可以用于進(jìn)程間通信(InterProcessCommunication,IPC),解決不同Android應(yīng)用程序進(jìn)程之間的調(diào)用和通訊問(wèn)題7.1

Service簡(jiǎn)介Service生命周期Service生命周期包括完全生命周期活動(dòng)生命周期onCreate()事件回調(diào)函數(shù):

Service的生命周期開(kāi)始,完成Service的初始化工作onStart()事件回調(diào)函數(shù):活動(dòng)生命周期開(kāi)始,但沒(méi)有與之對(duì)應(yīng)的“停止”函數(shù),因此可以近似認(rèn)為活動(dòng)生命周期也是以onDestroy()標(biāo)志結(jié)束onDestroy()事件回調(diào)函數(shù):

Service的生命周期結(jié)束,釋放Service所有占用的資源7.1

Service簡(jiǎn)介Service生命周期Service生命周期包括完全生命周期活動(dòng)生命周期還有三個(gè)事件回調(diào)函數(shù),分別是onCreate()、onStart()和onDestroy(),如下圖所示7.1

Service簡(jiǎn)介Service生命周期Service生命周期包括完整生命周期從onCreate()開(kāi)始到onDestroy()結(jié)束,在onCreate()中完成Service的初始化工作,在onDestroy()中釋放所有占用的資源活動(dòng)生命周期從onStart()開(kāi)始,但沒(méi)有與之對(duì)應(yīng)的“停止”函數(shù),因此可以粗略的認(rèn)為活動(dòng)生命周期是以onDestroy()標(biāo)志結(jié)束Service的使用方式一般有兩種啟動(dòng)方式綁定方式7.1

Service簡(jiǎn)介啟動(dòng)方式通過(guò)調(diào)用Context.startService()啟動(dòng)Service,通過(guò)調(diào)用Context.stopService()或Service.stopSelf()停止Service。因此,Service一定是由其它的組件啟動(dòng)的,但停止過(guò)程可以通過(guò)其它組件或自身完成在啟動(dòng)方式中,啟動(dòng)Service的組件不能夠獲取到Service的對(duì)象實(shí)例,因此無(wú)法調(diào)用Service中的任何函數(shù),也不能夠獲取到Service中的任何狀態(tài)和數(shù)據(jù)信息能夠以啟動(dòng)方式使用的Service,需要具備自管理的能力,而且不需要從通過(guò)函數(shù)調(diào)用獲取Service的功能和數(shù)據(jù)7.1

Service簡(jiǎn)介綁定方式Service的使用是通過(guò)服務(wù)鏈接(Connection)實(shí)現(xiàn)的,服務(wù)鏈接能夠獲取Service的對(duì)象實(shí)例,因此綁定Service的組件可以調(diào)用Service中實(shí)現(xiàn)的函數(shù),或直接獲取Service中的狀態(tài)和數(shù)據(jù)信息使用Service的組件通過(guò)Context.bindService()建立服務(wù)鏈接,通過(guò)Context.unbindService()停止服務(wù)鏈接如果在綁定過(guò)程中Service沒(méi)有啟動(dòng),Context.bindService()會(huì)自動(dòng)啟動(dòng)Service,而且同一個(gè)Service可以綁定多個(gè)服務(wù)鏈接,這樣可以同時(shí)為多個(gè)不同的組件提供服務(wù)7.1

Service簡(jiǎn)介啟動(dòng)方式和綁定方式的結(jié)合這兩種使用方法并不是完全獨(dú)立的,在某些情況下可以混合使用以MP3播放器為例,在后臺(tái)的工作的Service通過(guò)Context.startService()啟動(dòng)某個(gè)音樂(lè)播放,但在播放過(guò)程中如果用戶需要暫停音樂(lè)播放,則需要通過(guò)Context.bindService()獲取服務(wù)鏈接和Service對(duì)象實(shí)例,進(jìn)而通過(guò)調(diào)用Service對(duì)象實(shí)例中的函數(shù),暫停音樂(lè)播放過(guò)程,并保存相關(guān)信息在這種情況下,如果調(diào)用Context.stopService()并不能夠停止Service,需要在所有的服務(wù)鏈接關(guān)閉后,Service才能夠真正的停止7.2本地服務(wù)本地服務(wù)的調(diào)用者和服務(wù)都在同一個(gè)程序中,是不需要跨進(jìn)程就可以實(shí)現(xiàn)服務(wù)的調(diào)用本地服務(wù)涉及服務(wù)的建立、啟動(dòng)和停止,服務(wù)的綁定和取消綁定,以及如何在線程中實(shí)現(xiàn)服務(wù)7.2.1服務(wù)管理服務(wù)管理主要指服務(wù)的啟動(dòng)和停止首先說(shuō)明如何在代碼中實(shí)現(xiàn)Service。Service是一段在后臺(tái)運(yùn)行、沒(méi)有用戶界面的代碼,其最小代碼集如下7.2本地服務(wù)本地服務(wù)的調(diào)用者和服務(wù)都在同一個(gè)程序中,是不需要跨進(jìn)程就可以實(shí)現(xiàn)服務(wù)的調(diào)用本地服務(wù)涉及服務(wù)的建立、啟動(dòng)和停止,服務(wù)的綁定和取消綁定,以及如何在線程中實(shí)現(xiàn)服務(wù)7.2.1服務(wù)管理服務(wù)管理主要指服務(wù)的啟動(dòng)和停止首先說(shuō)明如何在代碼中實(shí)現(xiàn)Service。Service是一段在后臺(tái)運(yùn)行、沒(méi)有用戶界面的代碼,其最小代碼集如下7.2本地服務(wù)7.2.1服務(wù)管理7importandroid.app.Service;8importandroid.content.Intent;9importandroid.os.IBinder;1011publicclassRandomServiceextendsService{12@Override13publicIBinderonBind(Intentintent){14returnnull;15}16}7.2本地服務(wù)7.2.1服務(wù)管理除了在第1行到第3行引入必要包外,僅在第5行聲明了RandomService繼承了android.app.Service類,在第7行到第9行重載了onBind()函數(shù)onBind()函數(shù)是在Service被綁定后調(diào)用的函數(shù),能夠返回Service的對(duì)象實(shí)例7.2本地服務(wù)7.2.1服務(wù)管理這個(gè)Service最小代碼集并沒(méi)有任何實(shí)際的功能,為了使Service具有實(shí)際意義,一般需要重載onCreate()、onStart()和onDestroy()。Android系統(tǒng)在創(chuàng)建Service時(shí),會(huì)自動(dòng)調(diào)用onCreate(),用戶一般在onCreate()完成必要的初始化工作,例如創(chuàng)建線程、建立數(shù)據(jù)庫(kù)鏈接等在Service關(guān)閉前,系統(tǒng)會(huì)自動(dòng)調(diào)用onDestroy()函數(shù)釋放所有占用的資源。通過(guò)Context.startService(Intent)啟動(dòng)Service,onStart()則會(huì)被調(diào)用,重要的參數(shù)通過(guò)參數(shù)Intent傳遞給Service當(dāng)然,不是所有的Service都需要重載這三個(gè)函數(shù),可以根據(jù)實(shí)際情況選擇需要重載的函數(shù)7.2本地服務(wù)7.2.1服務(wù)管理1publicclassRandomServiceextendsService{2@Override3publicvoidonCreate(){4super.onCreate();5}6@Override7publicvoidonStart(Intentintent,intstartId){8super.onStart(intent,startId);9}10@Override11publicvoidonDestroy(){12super.onDestroy();13}14}7.2本地服務(wù)7.2.1服務(wù)管理1publicclassRandomServiceextendsService{2@Override3publicvoidonCreate(){4super.onCreate();5}6@Override7publicvoidonStart(Intentintent,intstartId){8super.onStart(intent,startId);9}10@Override11publicvoidonDestroy(){12super.onDestroy();13}14}7.2本地服務(wù)7.2.1服務(wù)管理重載onCreate()、onStart()和onDestroy()三個(gè)函數(shù)時(shí),務(wù)必要在代碼中調(diào)用父函數(shù),如代碼的第4行、第8行和第12行完成Service類后,需要在AndroidManifest.xml文件中注冊(cè)這個(gè)Service注冊(cè)Service非常重要,如果開(kāi)發(fā)人員不對(duì)Service進(jìn)行注冊(cè),則Service根本無(wú)法啟動(dòng)AndroidManifest.xml文件中注冊(cè)Service的代碼如下1<serviceandroid:name=".RandomService"/>使用<service>標(biāo)簽聲明服務(wù),其中的android:name表示Service類的名稱,一定要與建立的Service類名稱一致7.2本地服務(wù)7.2.1服務(wù)管理在完成Service代碼和在AndroidManifest.xml文件中注冊(cè)后,下面來(lái)說(shuō)明如何啟動(dòng)和停止Service。有兩種方法啟動(dòng)Service,顯式啟動(dòng)和隱式啟動(dòng)顯式啟動(dòng)需要在Intent中指明Service所在的類,并調(diào)用startService(Intent)啟動(dòng)Service,示例代碼如下1finalIntentserviceIntent=newIntent(this,RandomService.class);2startService(serviceIntent);在上面的代碼中,Intent指明了啟動(dòng)的Service所在類為RandomSerevice7.2本地服務(wù)7.2.1服務(wù)管理隱式啟動(dòng)則需要在注冊(cè)Service時(shí),聲明Intent-filter的action屬性1<serviceandroid:name=".RandomService">2<intent-filter>3<actionandroid:name="edu.hrbeu.RandomService"/>4</intent-filter>5</service>7.2本地服務(wù)7.2.1服務(wù)管理在隱式啟動(dòng)Service時(shí),需要設(shè)置Intent的action屬性,這樣則可以在不聲明Service所在類的情況下啟動(dòng)服務(wù)。隱式啟動(dòng)的代碼如下1finalIntentserviceIntent=newIntent();2serviceIntent.setAction("edu.hrbeu.RandomService");如果Service和調(diào)用服務(wù)的組件在同一個(gè)應(yīng)用程序中,可以使用顯式啟動(dòng)或隱式啟動(dòng),顯式啟動(dòng)更加易于使用,且代碼簡(jiǎn)潔。但如果服務(wù)和調(diào)用服務(wù)的組件在不同的應(yīng)用程序中,則只能使用隱式啟動(dòng)7.2本地服務(wù)7.2.1服務(wù)管理無(wú)論是顯式啟動(dòng)還是隱式啟動(dòng),停止Service的方法都是相同的,將啟動(dòng)Service的Intent傳遞給stopService(Intent)函數(shù)即可,示例代碼如下1stopService(serviceIntent);在首次調(diào)用startService(Intent)函數(shù)啟動(dòng)Service后,系統(tǒng)會(huì)先后調(diào)用onCreate()和onStart()果是第二次調(diào)用startService(Intent)函數(shù),系統(tǒng)則僅調(diào)用onStart(),而不再調(diào)用onCreate()在調(diào)用stopService(Intent)函數(shù)停止Service時(shí),系統(tǒng)會(huì)調(diào)用onDestroy()無(wú)論調(diào)用過(guò)多少次startService(Intent),在調(diào)用stopService(Intent)函數(shù)時(shí),系統(tǒng)僅調(diào)用一次onDestroy()7.2本地服務(wù)7.2.1服務(wù)管理SimpleRandomServiceDemo是在應(yīng)用程序中使用Service的示例,這個(gè)示例使用顯式啟動(dòng)的方式啟動(dòng)Service在工程中創(chuàng)建了RandomService服務(wù),該服務(wù)啟動(dòng)后會(huì)產(chǎn)生一個(gè)隨機(jī)數(shù),并使用Toast顯示在屏幕上,如右圖所示7.2本地服務(wù)7.2.1服務(wù)管理示例通過(guò)界面上的“啟動(dòng)Service”按鈕調(diào)用startService(Intent)函數(shù),啟動(dòng)RandomService服務(wù)“停止Service”按鈕調(diào)用stopService(Intent)函數(shù),停止RandomService服務(wù)為了能夠清晰的觀察Service中onCreate()、onStart()和onDestroy()三個(gè)函數(shù)的調(diào)用順序,在每個(gè)函數(shù)中都使用Toast在界面上產(chǎn)生提示信息RandomService.java文件的代碼如下7.2本地服務(wù)7.2.1服務(wù)管理RandomService.java文件的代碼1packageedu.hrbeu.SimpleRandomServiceDemo;23importandroid.app.Service;4importandroid.content.Intent;5importandroid.os.IBinder;6importandroid.widget.Toast;78publicclassRandomServiceextendsService{910@Override11publicvoidonCreate(){12super.onCreate();13Toast.makeText(this,"(1)調(diào)用onCreate()",7.2本地服務(wù)7.2.1服務(wù)管理RandomService.java文件的代碼14Toast.LENGTH_LONG).show();15}1617@Override18publicvoidonStart(Intentintent,intstartId){19super.onStart(intent,startId);20Toast.makeText(this,"(2)調(diào)用onStart()",21Toast.LENGTH_SHORT).show();2223doublerandomDouble=Math.random();24Stringmsg="隨機(jī)數(shù):"+String.valueOf(randomDouble);25Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();26}7.2本地服務(wù)7.2.1服務(wù)管理RandomService.java文件的代碼2728@Override29publicvoidonDestroy(){30super.onDestroy();31Toast.makeText(this,"(3)調(diào)用onDestroy()",32Toast.LENGTH_SHORT).show();33}3435@Override36publicIBinderonBind(Intentintent){37returnnull;38}39}7.2本地服務(wù)7.2.1服務(wù)管理示例在onStart()函數(shù)中添加生產(chǎn)隨機(jī)數(shù)的代碼,第23行生產(chǎn)一個(gè)介于0和1之間的隨機(jī)數(shù),并在第24行構(gòu)造供Toast顯示的消息AndroidManifest.xml文件的代碼如下1<?xmlversion="1.0"encoding="utf-8"?>2<manifestxmlns:android="/apk/res/android"3package="edu.hrbeu.SimpleRandomServiceDemo"4android:versionCode="1"5android:versionName="1.0">6<applicationandroid:icon="@drawable/icon"android:label="@string/app_name">7.2本地服務(wù)7.2.1服務(wù)管理AndroidManifest.xml文件的代碼7<activityandroid:name=".SimpleRandomServiceDemo"8android:label="@string/app_name">9<intent-filter>10<actionandroid:name="ent.action.MAIN"/>11<categoryandroid:name="ent.category.LAUNCHER"/>12</intent-filter>13</activity>14<serviceandroid:name=".RandomService"/>15</application>16<uses-sdkandroid:minSdkVersion="14"/>17</manifest>7.2本地服務(wù)7.2.1服務(wù)管理示例在調(diào)用AndroidManifest.xml文件中,在<application>標(biāo)簽下,包含一個(gè)<activity>標(biāo)簽和一個(gè)<service>標(biāo)簽,在<service>標(biāo)簽中,聲明了RandomService所在的類SimpleRandomServiceDemoActivity.java文件的代碼如下1packageedu.hrbeu.SimpleRandomServiceDemo;23importandroid.app.Activity;4importandroid.content.Intent;5importandroid.os.Bundle;6importandroid.view.View;7importandroid.widget.Button;7.2本地服務(wù)7.2.1服務(wù)管理SimpleRandomServiceDemoActivity.java文件的代碼89publicclassSimpleRandomServiceDemoActivityextendsActivity{10@Override11publicvoidonCreate(BundlesavedInstanceState){12super.onCreate(savedInstanceState);13setContentView(R.layout.main);1415ButtonstartButton=(Button)findViewById(R.id.start);16ButtonstopButton=(Button)findViewById(R.id.stop);17finalIntentserviceIntent=newIntent(this,RandomService.class);18startButton.setOnClickListener(newButton.OnClickListener(){19publicvoidonClick(Viewview){20startService(serviceIntent);7.2本地服務(wù)7.2.1服務(wù)管理SimpleRandomServiceDemoActivity.java文件的代碼21}22});23stopButton.setOnClickListener(newButton.OnClickListener(){24publicvoidonClick(Viewview){25stopService(serviceIntent);26}27});28}29}7.2本地服務(wù)7.2.1服務(wù)管理示例SimpleRandomServiceDemoActivity.java文件是應(yīng)用程序中的Activity代碼,第20行和第25行分別是啟動(dòng)和停止Service的代碼隱式啟動(dòng)Service的示例代碼,參考ImplicityRandomServiceDemo示例7.2本地服務(wù)7.2.2使用線程在Android系統(tǒng)中,Activity、Service和BroadcastReceiver都是工作在主線程上,因此任何耗時(shí)的處理過(guò)程都會(huì)降低用戶界面的響應(yīng)速度,甚至導(dǎo)致用戶界面失去響應(yīng)當(dāng)用戶界面失去響應(yīng)超過(guò)5秒后,Android系統(tǒng)會(huì)允許用戶強(qiáng)行關(guān)閉應(yīng)用程序,提示如下圖所示7.2本地服務(wù)7.2.2使用線程因此,較好的解決方法是將耗時(shí)的處理過(guò)程轉(zhuǎn)移到子線程上,這樣可以縮短主線程的事件處理時(shí)間,從而避免用戶界面長(zhǎng)時(shí)間失去響應(yīng)“耗時(shí)的處理過(guò)程”一般指復(fù)雜運(yùn)算過(guò)程、大量的文件操作、存在延時(shí)的網(wǎng)絡(luò)通訊和數(shù)據(jù)庫(kù)操作等等線程是獨(dú)立的程序單元,多個(gè)線程可以并行工作。在多處理器系統(tǒng)中,每個(gè)中央處理器(CPU)單獨(dú)運(yùn)行一個(gè)線程,因此線程是并行工作的但在單處理器系統(tǒng)中,處理器會(huì)給每個(gè)線程一小段時(shí)間,在這個(gè)時(shí)間內(nèi)線程是被執(zhí)行的,然后處理器執(zhí)行下一個(gè)線程,這樣就產(chǎn)生了線程并行運(yùn)行的假象7.2本地服務(wù)7.2.2使用線程無(wú)論線程是否真的并行工作,在宏觀上可以認(rèn)為子線程是獨(dú)立于主線程的,且能與主線程并行工作的程序單元在Java語(yǔ)言中,建立和使用線程比較簡(jiǎn)單,首先需要實(shí)現(xiàn)Java的Runnable接口,并重載run()函數(shù),在run()中放置代碼的主體部分1privateRunnablebackgroudWork=newRunnable(){2@Override3publicvoidrun(){4//過(guò)程代碼5}6};7.2本地服務(wù)7.2.2使用線程然后創(chuàng)建Thread對(duì)象,并將Runnable對(duì)象作為參數(shù)傳遞給Thread對(duì)象在Thread的構(gòu)造函數(shù)中,第1個(gè)參數(shù)用來(lái)表示線程組,第2個(gè)參數(shù)是需要執(zhí)行的Runnable對(duì)象,第3個(gè)參數(shù)是線程的名稱1privateThreadworkThread;2workThread=newThread(null,backgroudWork,"WorkThread");最后,調(diào)用start()方法啟動(dòng)線程1workThread.start();7.2本地服務(wù)7.2.2使用線程當(dāng)線程在run()方法返回后,線程就自動(dòng)終止了當(dāng)然,也可以調(diào)用stop()在外部終止線程,但這種方法并不推薦使用,因?yàn)檫@方法并不安全,有一定可能性會(huì)產(chǎn)生異常最好的方法是通知線程自行終止,一般調(diào)用interrupt()方法通告線程準(zhǔn)備終止,線程會(huì)釋放它正在使用的資源,在完成所有的清理工作后自行關(guān)閉workTerrupt();其實(shí)interrupt()方法并不能直接終止線程,僅是改變了線程內(nèi)部的一個(gè)布爾值,run()方法能夠檢測(cè)到這個(gè)布爾值的改變,從而在適當(dāng)?shù)臅r(shí)候釋放資源和終止線程7.2本地服務(wù)7.2.2使用線程在run()中的代碼一般通過(guò)Terrupted()方法查詢線程是否被中斷一般情況下,子線程需要無(wú)限運(yùn)行,除非外部調(diào)用interrupt()方法中斷線程,所以通常會(huì)將程序主體放置在while()函數(shù)內(nèi),并調(diào)用Terrupted()方法判斷線程是否應(yīng)被中斷下面的代碼中,以1秒為間隔循環(huán)檢測(cè)線程是否應(yīng)被中斷1publicvoidrun(){2while(!Terrupted()){3//過(guò)程代碼4Thread.sleep(1000);5}6}7.2本地服務(wù)7.2.2使用線程第4行代碼使線程休眠1000毫秒當(dāng)線程在休眠過(guò)程中線程被中斷,則會(huì)產(chǎn)生InterruptedException異常因此代碼中需要捕獲InterruptedException異常,保證安全終止線程7publicvoidrun(){1try{2while(true){3//過(guò)程代碼4Thread.sleep(1000);5}6}catch(InterruptedExceptione){7e.printStackTrace();8}9}7.2本地服務(wù)7.2.2使用線程使用Handler更新用戶界面Handler允許將Runnable對(duì)象發(fā)送到線程的消息隊(duì)列中,每個(gè)Handler實(shí)例綁定到一個(gè)單獨(dú)的線程和消息隊(duì)列上當(dāng)用戶建立一個(gè)新的Handler實(shí)例,通過(guò)post()方法將Runnable對(duì)象從后臺(tái)線程發(fā)送給GUI線程的消息隊(duì)列,當(dāng)Runnable對(duì)象通過(guò)消息隊(duì)列后,這個(gè)Runnable對(duì)象將被運(yùn)行7.2本地服務(wù)7.2.2使用線程1privatestaticHandlerhandler=newHandler();23publicstaticvoidUpdateGUI(doublerefreshDouble){4handler.post(RefreshLable);5}6privatestaticRunnableRefreshLable=newRunnable(){7@Override8publicvoidrun(){9//過(guò)程代碼10}11};7.2本地服務(wù)7.2.2使用線程第1行建立了一個(gè)靜態(tài)的Handler實(shí)例,但這個(gè)實(shí)例是私有的,因此外部代碼并不能直接調(diào)用這個(gè)Handler實(shí)例第3行UpdateGUI()是公有的界面更新函數(shù),后臺(tái)線程通過(guò)調(diào)用該函數(shù),將后臺(tái)產(chǎn)生的數(shù)據(jù)refreshDouble傳遞到UpdateGUI()函數(shù)內(nèi)部,然后直接調(diào)用post()方法,將第6行創(chuàng)建的Runnable對(duì)象傳遞給界面線程(主線程)的消息隊(duì)列中第8行到第10行代碼是Runnable對(duì)象中需要重載的run()函數(shù),界面更新代碼就在這里7.2本地服務(wù)7.2.2使用線程ThreadRandomServiceDemo是使用線程持續(xù)產(chǎn)生隨機(jī)數(shù)的示例點(diǎn)擊“啟動(dòng)Service”后將啟動(dòng)后臺(tái)線程點(diǎn)擊“停止Service”將關(guān)閉后臺(tái)線程后臺(tái)線程每1秒鐘產(chǎn)生一個(gè)0到1之間的隨機(jī)數(shù),并通過(guò)Handler將產(chǎn)生的隨機(jī)數(shù)顯示在用戶界面上。ThreadRandomServiceDemo的用戶界面如下圖所示7.2本地服務(wù)7.2.2使用線程在ThreadRandomServiceDemo示例中,RandomService.java文件是定義Service的文件,用來(lái)創(chuàng)建線程、產(chǎn)生隨機(jī)數(shù)和調(diào)用界面更新函數(shù)ThreadRandomServiceDemoActivity.java文件是用戶界面的Activity文件,封裝Handler界面更新的函數(shù)就在這個(gè)文件中下面是RandomService.java和ThreadRandomServiceDemoActivity.java文件的完整代碼7.2本地服務(wù)7.2.2使用線程RandomService.java文件代碼1packageedu.hrbeu.ThreadRandomServiceDemo;23importandroid.app.Service;4importandroid.content.Intent;5importandroid.os.IBinder;6importandroid.widget.Toast;78publicclassRandomServiceextendsService{910privateThreadworkThread;1112@Override7.2本地服務(wù)7.2.2使用線程RandomService.java文件代碼13publicvoidonCreate(){14super.onCreate();15Toast.makeText(this,"(1)調(diào)用onCreate()",16Toast.LENGTH_LONG).show();17workThread=newThread(null,backgroudWork,"WorkThread");18}1920@Override21publicvoidonStart(Intentintent,intstartId){22super.onStart(intent,startId);23Toast.makeText(this,"(2)調(diào)用onStart()",24Toast.LENGTH_SHORT).show();7.2本地服務(wù)7.2.2使用線程RandomService.java文件代碼25if(!workThread.isAlive()){26workThread.start();27}28}2930@Override31publicvoidonDestroy(){32super.onDestroy();33Toast.makeText(this,"(3)調(diào)用onDestroy()",34Toast.LENGTH_SHORT).show();35workTerrupt();36}7.2本地服務(wù)7.2.2使用線程RandomService.java文件代碼3738@Override39publicIBinderonBind(Intentintent){40returnnull;41}4243privateRunnablebackgroudWork=newRunnable(){44@Override45publicvoidrun(){46try{47while(!Terrupted()){48doublerandomDouble=Math.random();7.2本地服務(wù)7.2.2使用線程RandomService.java文件代碼49ThreadRandomServiceDemoActivity.UpdateGUI(randomDouble);50Thread.sleep(1000);51}52}catch(InterruptedExceptione){53e.printStackTrace();54}55}56};57}7.2本地服務(wù)7.2.2使用線程ThreadRandomServiceDemoActivity.java文件代碼1packageedu.hrbeu.ThreadRandomServiceDemo;23importandroid.app.Activity;4importandroid.content.Intent;5importandroid.os.Bundle;6importandroid.os.Handler;7importandroid.view.View;8importandroid.widget.Button;9importandroid.widget.TextView;1011publicclassThreadRandomServiceDemoActivityextendsActivity{12

7.2本地服務(wù)7.2.2使用線程ThreadRandomServiceDemoActivity.java文件代碼13privatestaticHandlerhandler=newHandler();14privatestaticTextViewlabelView=null;15privatestaticdoublerandomDouble;1617publicstaticvoidUpdateGUI(doublerefreshDouble){18randomDouble=refreshDouble;19handler.post(RefreshLable);20}2122privatestaticRunnableRefreshLable=newRunnable(){23@Override24publicvoidrun(){7.2本地服務(wù)7.2.2使用線程ThreadRandomServiceDemoActivity.java文件代碼25labelView.setText(String.valueOf(randomDouble));26}27};2829@Override30publicvoidonCreate(BundlesavedInstanceState){31super.onCreate(savedInstanceState);32setContentView(R.layout.main);33labelView=(TextView)findViewById(R.id.label);34ButtonstartButton=(Button)findViewById(R.id.start);35ButtonstopButton=(Button)findViewById(R.id.stop);36finalIntentserviceIntent=newIntent(this,RandomService.class);7.2本地服務(wù)7.2.2使用線程ThreadRandomServiceDemoActivity.java文件代碼3738startButton.setOnClickListener(newButton.OnClickListener(){39publicvoidonClick(Viewview){40startService(serviceIntent);41}42});4344stopButton.setOnClickListener(newButton.OnClickListener(){45publicvoidonClick(Viewview){46stopService(serviceIntent);47}48});49}50}7.2本地服務(wù)7.2.3

服務(wù)綁定以綁定方式使用Service,能夠獲取到Service實(shí)例,不僅能夠正常啟動(dòng)Service,還能夠調(diào)用Service中的公有方法和屬性為了使Service支持綁定,需要在Service類中重載onBind()方法,并在onBind()方法中返回Service實(shí)例,示例代碼如下7.2本地服務(wù)7.2.3服務(wù)綁定1publicclassMathServiceextendsService{2privatefinalIBindermBinder=newLocalBinder();34publicclassLocalBinderextendsBinder{5MathServicegetService(){6returnMathService.this;7}8}910@Override11publicIBinderonBind(Intentintent){12returnmBinder;13}14}7.2本地服務(wù)7.2.3

服務(wù)綁定當(dāng)Service被綁定時(shí),系統(tǒng)會(huì)調(diào)用onBind()函數(shù),通過(guò)onBind()函數(shù)的返回值,將Service實(shí)例返回給調(diào)用者從第11行代碼中可以看出,onBind()函數(shù)的返回值必須符合IBinder接口,因此在代碼的第2行聲明一個(gè)接口變量mBinder,mBinder符合onBind()函數(shù)返回值的要求,因此可將mBinder傳遞給調(diào)用者IBinder是用于進(jìn)程內(nèi)部和進(jìn)程間過(guò)程調(diào)用的輕量級(jí)接口,定義了與遠(yuǎn)程對(duì)象交互的抽象協(xié)議,使用時(shí)通過(guò)繼承Binder的方法來(lái)實(shí)現(xiàn)繼承Binder的代碼在第4行,LocalBinder是繼承Binder的一個(gè)內(nèi)部類,并在代碼第5行實(shí)現(xiàn)了getService()函數(shù),當(dāng)調(diào)用者獲取到mBinder后,通過(guò)調(diào)用getService()即可獲取到Service實(shí)例7.2本地服務(wù)7.2.3

服務(wù)綁定調(diào)用者通過(guò)bindService()函數(shù)綁定服務(wù)調(diào)用者通過(guò)bindService()函數(shù)綁定服務(wù),并在第1個(gè)參數(shù)中將Intent傳遞給bindService()函數(shù),聲明需要啟動(dòng)的Service第3個(gè)參數(shù)Context.BIND_AUTO_CREATE表明只要綁定存在,就自動(dòng)建立Service同時(shí)也告知Android系統(tǒng),這個(gè)Service的重要程度與調(diào)用者相同,除非考慮終止調(diào)用者,否則不要關(guān)閉這個(gè)Service1finalIntentserviceIntent=newIntent(this,MathService.class);2bindService(serviceIntent,mConnection,Context.BIND_AUTO_CREATE);7.2本地服務(wù)7.2.3

服務(wù)綁定bindService()函數(shù)的第2個(gè)參數(shù)是ServiceConnnection當(dāng)綁定成功后,系統(tǒng)將調(diào)用ServiceConnnection的onServiceConnected()方法當(dāng)綁定意外斷開(kāi)后,系統(tǒng)將調(diào)用ServiceConnnection中的onServiceDisconnected方法因此,以綁定方式使用Service,調(diào)用者需要聲明一個(gè)ServiceConnnection,并重載內(nèi)部的onServiceConnected()方法和onServiceDisconnected方法,兩個(gè)方法的重載代碼如下7.2本地服務(wù)7.2.3

服務(wù)綁定1privateServiceConnectionmConnection=newServiceConnection(){2@Override3publicvoidonServiceConnected(ComponentNamename,IBinderservice){4mathService=((MathService.LocalBinder)service).getService();5}6@Override7publicvoidonServiceDisconnected(ComponentNamename){8mathService=null;9}10};7.2本地服務(wù)7.2.3

服務(wù)綁定在代碼的第4行中,綁定成功后通過(guò)getService()獲取Service實(shí)例,這樣便可以調(diào)用Service中的方法和屬性代碼第8行將Service實(shí)例指為null,表示綁定意外失效時(shí),Service實(shí)例不再可用取消綁定僅需要使用unbindService()方法,并將ServiceConnnection傳遞給unbindService()方法但需要注意的是,unbindService()方法成功后,系統(tǒng)并不會(huì)調(diào)用onServiceConnected(),因?yàn)閛nServiceConnected()僅在意外斷開(kāi)綁定時(shí)才被調(diào)用1unbindService(mConnection);7.2本地服務(wù)7.2.3

服務(wù)綁定綁定方式中,當(dāng)調(diào)用者通過(guò)bindService()函數(shù)綁定Servcie時(shí),onCreate()函數(shù)和onBinde()函數(shù)將被先后調(diào)用當(dāng)調(diào)用者通過(guò)unbindService()函數(shù)取消綁定Servcie時(shí),onUnbind()函數(shù)將被調(diào)用。如果onUnbind()函數(shù)返回true,則表示重新綁定服務(wù)時(shí),onRebind()函數(shù)將被調(diào)用。綁定方式的函數(shù)調(diào)用順序如下圖所示7.2本地服務(wù)7.2.3

服務(wù)綁定SimpleMathServiceDemo是綁定方式使用Service的示例在示例中創(chuàng)建了MathService服務(wù),用來(lái)完成簡(jiǎn)單的數(shù)學(xué)運(yùn)算,這里的數(shù)學(xué)運(yùn)算僅指加法運(yùn)算,雖然沒(méi)有實(shí)際意義,但可以說(shuō)明如何使用綁定方式調(diào)用Service中的公有方法在服務(wù)綁定后,用戶可以點(diǎn)擊“加法運(yùn)算”,將兩個(gè)隨機(jī)產(chǎn)生的數(shù)值傳遞給MathService服務(wù),并從MathService實(shí)例中獲取到加法運(yùn)算的結(jié)果,然后顯示在屏幕的上方“取消綁定”按鈕可以解除與MathService的綁定關(guān)系,在取消綁定后,點(diǎn)擊“加法運(yùn)算”按鈕將無(wú)法獲取運(yùn)算結(jié)果7.2本地服務(wù)7.2.3

服務(wù)綁定SimpleMathServiceDemo是綁定方式使用Service的示例SimpleMathServiceDemo的用戶界面如下圖所示7.2本地服務(wù)7.2.3

服務(wù)綁定SimpleMathServiceDemo是綁定方式使用Service的示例在SimpleMathServiceDemo示例中,MathService.java文件是Service的定義文件SimpleMathServiceDemoActivity.java文件是界面的Activity文件,綁定服務(wù)和取消綁定服務(wù)的代碼在這個(gè)文件中下面是MathService.java和SimpleMathServiceDemoActivity.java文件的完整代碼

7.2本地服務(wù)7.2.3服務(wù)綁定MathService.java文件代碼1packageedu.hrbeu.SimpleMathServiceDemo;23importandroid.app.Service;4importandroid.content.Intent;5importandroid.os.Binder;6importandroid.os.IBinder;7importandroid.widget.Toast;89publicclassMathServiceextendsService{1011privatefinalIBindermBinder=newLocalBinder();12

7.2本地服務(wù)7.2.3服務(wù)綁定MathService.java文件代碼13publicclassLocalBinderextendsBinder{14MathServicegetService(){15returnMathService.this;16}17}1819@Override20publicIBinderonBind(Intentintent){21Toast.makeText(this,"本地綁定:MathService",22Toast.LENGTH_SHORT).show();23returnmBinder;24}7.2本地服務(wù)7.2.3服務(wù)綁定MathService.java文件代碼2526@Override27publicbooleanonUnbind(Intentintent){28Toast.makeText(this,"取消本地綁定:MathService",29Toast.LENGTH_SHORT).show();30returnfalse;31}323334publiclongAdd(longa,longb){35returna+b;36}3738}7.2本地服務(wù)7.2.3服務(wù)綁定SimpleMathServiceDemoActivity.java文件代碼1packageedu.hrbeu.SimpleMathServiceDemo;23importandroid.app.Activity;4importandroid.content.ComponentName;5importandroid.content.Context;6importandroid.content.Intent;7importandroid.content.ServiceConnection;8importandroid.os.Bundle;9importandroid.os.IBinder;10importandroid.view.View;11importandroid.widget.Button;12importandroid.widget.TextView;7.2本地服務(wù)7.2.3服務(wù)綁定SimpleMathServiceDemoActivity.java文件代碼1314publicclassSimpleMathServiceDemoActivityextendsActivity{15privateMathServicemathService;16privatebooleanisBound=false;17TextViewlabelView;18@Override19publicvoidonCreate(BundlesavedInstanceState){20super.onCreate(savedInstanceState);21setContentView(R.layout.main);2223labelView=(TextView)findViewById(R.id.label);24ButtonbindButton=(Button)findViewById(R.id.bind);7.2本地服務(wù)7.2.3服務(wù)綁定SimpleMathServiceDemoActivity.java文件代碼25ButtonunbindButton=(Button)findViewById(R.id.unbind);26ButtoncomputButton=(Button)findViewById(R.pute);2728bindButton.setOnClickListener(newView.OnClickListener(){29@Override30publicvoidonClick(Viewv){31if(!isBound){32finalIntentserviceIntent=newIntent(SimpleMathServiceDemoActivity.this,MathService.class);33bindService(serviceIntent,mConnection,Context.BIND_AUTO_CREATE);34isBound=true;35}36}

7.2本地服務(wù)7.2.3服務(wù)綁定SimpleMathServiceDemoActivity.java文件代碼37});3839unbindButton.setOnClickListener(newView.OnClickListener(){40@Override41publicvoidonClick(Viewv){42if(isBound){43isBound=false;44unbindService(mConnection);45mathService=null;46}47}48});7.2本地服務(wù)7.2.3服務(wù)綁定SimpleMathServiceDemoActivity.java文件代碼4950computButton.setOnClickListener(newView.OnClickListener(){51@Override52publicvoidonClick(Viewv){53if(mathService==null){54labelView.setText("未綁定服務(wù)");55return;56}57longa=Math.round(Math.random()*100);58longb=Math.round(Math.random()*100);59longresult=mathService.Add(a,b);60Stringmsg=String.valueOf(a)+"+"+String.valueOf(b)+7.2本地服務(wù)7.2.3服務(wù)綁定SimpleMathServiceDemoActivity.java文件代碼61"="+String.valueOf(result);62labelView.setText(msg);63}64});65}6667privateServiceConnectionmConnection=newServiceConnection(){68@Override69publicvoidonServiceConnected(ComponentNamename,IBinderservice){70mathService=((MathService.LocalBinder)service).getService();71}72

7.2本地服務(wù)7.2.3服務(wù)綁定SimpleMathServiceDemoActivity.java文件代碼73@Override74publicvoidonServiceDisconnected(ComponentNamename){75mathService=null;76}77};78}7.3

遠(yuǎn)程服務(wù)

7.3.1進(jìn)程間通信在Android系統(tǒng)中,每個(gè)應(yīng)用程序在各自的進(jìn)程中運(yùn)行,而且出于安全原因的考慮,這些進(jìn)程之間彼此是隔離的,進(jìn)程之間傳遞數(shù)據(jù)和對(duì)象,需要使用Android支持的進(jìn)程間通信(Inter-ProcessCommunication,IPC)機(jī)制在Unix/Linux系統(tǒng)中,傳統(tǒng)的IPC機(jī)制包括共享內(nèi)存、管道、消息隊(duì)列和socket等等,這些IPC機(jī)制雖然被廣泛使用,但仍然存在著固有的缺陷,如容易產(chǎn)生錯(cuò)誤、難于維護(hù)等等在Android系統(tǒng)中,沒(méi)有使用傳統(tǒng)的IPC機(jī)制,而是采用Intent和遠(yuǎn)程服務(wù)的方式實(shí)現(xiàn)IPC,使應(yīng)用程序具有更好的獨(dú)立性和魯棒性7.3

遠(yuǎn)程服務(wù)

7.3.1進(jìn)程間通信Android系統(tǒng)允許應(yīng)用程序使用Intent啟動(dòng)Activity和Service,同時(shí)Intent可以傳遞數(shù)據(jù),是一種簡(jiǎn)單、高效、易于使用的IPC機(jī)制Android系統(tǒng)的另一種IPC機(jī)制就是遠(yuǎn)程服務(wù),服務(wù)和調(diào)用者在不同的兩個(gè)進(jìn)程

溫馨提示

  • 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)論