我的家園

          我的家園

          一、 Service簡(jiǎn)介

          Service是android 系統(tǒng)中的四大組件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的級(jí)別差不多,但不能自己運(yùn)行只能后臺(tái)運(yùn)行,并且可以和其他組件進(jìn)行交互。service可以在和多場(chǎng)合的應(yīng)用中使用,比如播放多媒體的時(shí)候用戶啟動(dòng)了其他Activity這個(gè)時(shí)候程序要在后臺(tái)繼續(xù)播放,比如檢測(cè)SD卡上文件的變化,再或者在后臺(tái)記錄你地理信息位置的改變等等,總之服務(wù)總是藏在后臺(tái)的。

          Service的啟動(dòng)有兩種方式:context.startService() context.bindService()


          二、 Service啟動(dòng)流程

          context.startService() 啟動(dòng)流程:


          context.startService()  -> onCreate()  -> onStart()  -> Service running  -> context.stopService()  -> onDestroy()  -> Service stop 

          如果Service還沒(méi)有運(yùn)行,則android先調(diào)用onCreate()然后調(diào)用onStart();

          如果Service已經(jīng)運(yùn)行,則只調(diào)用onStart(),所以一個(gè)Service的onStart方法可能會(huì)重復(fù)調(diào)用多次。 

          如果stopService的時(shí)候直接onDestroy,如果是調(diào)用者自己直接退出而沒(méi)有調(diào)用stopService的話,Service會(huì)一直在后臺(tái)運(yùn)行,該Service的調(diào)用者再啟動(dòng)起來(lái)后可以通過(guò)stopService關(guān)閉Service。

          所以調(diào)用startService的生命周期為:onCreate --> onStart(可多次調(diào)用) --> onDestroy


          context.bindService()啟動(dòng)流程:

          context.bindService()  -> onCreate()  -> onBind()  -> Service running  -> onUnbind()  -> onDestroy()  -> Service stop
           

          onBind()將返回給客戶端一個(gè)IBind接口實(shí)例,IBind允許客戶端回調(diào)服務(wù)的方法,比如得到Service的實(shí)例、運(yùn)行狀態(tài)或其他操作。這個(gè)時(shí)候把調(diào)用者(Context,例如Activity)會(huì)和Service綁定在一起,Context退出了,Srevice就會(huì)調(diào)用onUnbind->onDestroy相應(yīng)退出。 

          所以調(diào)用bindService的生命周期為:onCreate --> onBind(只一次,不可多次綁定) --> onUnbind --> onDestory。

          在Service每一次的開(kāi)啟關(guān)閉過(guò)程中,只有onStart可被多次調(diào)用(通過(guò)多次startService調(diào)用),其他onCreate,onBind,onUnbind,onDestory在一個(gè)生命周期中只能被調(diào)用一次。

           


          三、 Service生命周期 

          Service的生命周期并不像Activity那么復(fù)雜,它只繼承了onCreate()、onStart()、onDestroy()三個(gè)方法

          當(dāng)我們第一次啟動(dòng)Service時(shí),先后調(diào)用了onCreate()、onStart()這兩個(gè)方法;當(dāng)停止Service時(shí),則執(zhí)行onDestroy()方法。

          這里需要注意的是,如果Service已經(jīng)啟動(dòng)了,當(dāng)我們?cè)俅螁?dòng)Service時(shí),不會(huì)在執(zhí)行onCreate()方法,而是直接執(zhí)行onStart()方法。

          它可以通過(guò)Service.stopSelf()方法或者Service.stopSelfResult()方法來(lái)停止自己,只要調(diào)用一次stopService()方法便可以停止服務(wù),無(wú)論調(diào)用了多少次的啟動(dòng)服務(wù)方法。


          四、 Service示例

          下面我做了一個(gè)簡(jiǎn)單的音樂(lè)播放的應(yīng)用,分別使用startService和bindService來(lái)啟動(dòng)本地的服務(wù)。

          Activity


          Service


          AndroidManifest.xml

          注冊(cè)activity

          注冊(cè)service



          五、 代碼解析

          1、Activity中,PlayMusicService中通過(guò)重寫OnClickListener 接口onClick()方法實(shí)現(xiàn)對(duì)播放音樂(lè)的控制,把音樂(lè)各種操作用數(shù)字通過(guò)Intent傳遞給service

          然后通過(guò)構(gòu)造一個(gè)Intent , intent = new Intent("com.homer.service.musicService"); 

          其中,com.homer.service.musicService是 AndroidManifest.xml 對(duì)service的定義,即上面“注冊(cè)service”

          2、Activity中,音樂(lè)播放的控制,利用Bundle綁定數(shù)字op后,通過(guò) startService(intent); 服務(wù)后發(fā)送出去
          Bundle bundle = new Bundle();
          bundle.putInt("op", op);
          intent.putExtras(bundle);

          startService(intent);

          3、 Service中,會(huì)處理Activity啟動(dòng)的 startService(intent);服務(wù),依次調(diào)用service的啟動(dòng)過(guò)程:onCreate --> onStart(可多次調(diào)用) --> onDestroy

          onCreate(),  創(chuàng)建mediaPlayer

          onStart(),      通過(guò)獲取Bundle bundle = intent.getExtras();,提取int op = bundle.getInt("op");,然后執(zhí)行響應(yīng)的音樂(lè)播放操作

          onDestroy(),停止并釋放mediaPlayer音樂(lè)資源,如果當(dāng)執(zhí)行context.stopService()時(shí)調(diào)用此方法

          4、Activity中,onClick()函數(shù)中close與exit是執(zhí)行含義是不同的:

          close : 只是執(zhí)行了this.finish(); 關(guān)閉了本Activity窗體,service并沒(méi)有被關(guān)掉,音樂(lè)依然會(huì)繼續(xù)在后臺(tái)播放

          exit  : 先調(diào)用了stopService(intent); 關(guān)閉了service服務(wù),在Service中會(huì)調(diào)用3中的onDestroy()停止并釋放音樂(lè)資源,后才執(zhí)行this.finish(); 關(guān)閉了本Activity窗體


          源碼下載



          六、 拓展知識(shí)(進(jìn)程和聲明周期)

          Android操作系統(tǒng)嘗試盡可能長(zhǎng)時(shí)間的保持應(yīng)用的進(jìn)程,但當(dāng)可用內(nèi)存很低時(shí)最終要移走一部分進(jìn)程。怎樣確定那些程序可以運(yùn)行,那些要被銷毀,Android讓每一個(gè)進(jìn)程在一個(gè)重要級(jí)的基礎(chǔ)上運(yùn)行,重要級(jí)低的進(jìn)程最有可能被淘汰,一共有5級(jí),下面這個(gè)列表就是按照重要性排列的:

          1 一個(gè)前臺(tái)進(jìn)程顯示的是用戶此時(shí)需要處理和顯示的。下列的條件有任何一個(gè)成立,這個(gè)進(jìn)程都被認(rèn)為是在前臺(tái)運(yùn)行的。
                  a 與用戶正發(fā)生交互的。
                  b 它控制一個(gè)與用戶交互的必須的基本的服務(wù)。
                  c 有一個(gè)正在調(diào)用生命周期的回調(diào)函數(shù)的service(如onCreate()、onStar()、onDestroy())
                  d 它有一個(gè)正在運(yùn)行onReceive()方法的廣播接收對(duì)象。
          只有少數(shù)的前臺(tái)進(jìn)程可以在任何給定的時(shí)間內(nèi)運(yùn)行,銷毀他們是系統(tǒng)萬(wàn)不得已的、最后的選擇——當(dāng)內(nèi)存不夠系統(tǒng)繼續(xù)運(yùn)行下去時(shí)。通常,在這一點(diǎn)上,設(shè)備已經(jīng)達(dá)到了內(nèi)存分頁(yè)狀態(tài),所以殺掉一些前臺(tái)進(jìn)程來(lái)保證能夠響應(yīng)用戶的需求。

          2 一個(gè)可用進(jìn)程沒(méi)有任何前臺(tái)組件,但它仍然可以影響到用戶的界面。下面兩種情況發(fā)生時(shí),可以稱該進(jìn)程為可用進(jìn)程。
                  它是一個(gè)非前臺(tái)的activity,但對(duì)用戶仍然可用(onPause()方法已經(jīng)被調(diào)用)這是可能發(fā)生的,例如:前臺(tái)的activity是一個(gè)允許上一個(gè)activity可見(jiàn)的對(duì)話框,即當(dāng)前activity半透明,能看到前一個(gè)activity的界面,它是一個(gè)服務(wù)于可用activity的服務(wù)。

          3 一個(gè)服務(wù)進(jìn)程是一個(gè)通過(guò)調(diào)用startService()方法啟動(dòng)的服務(wù),并且不屬于前兩種情況。盡管服務(wù)進(jìn)程沒(méi)有直接被用戶看到,但他們確實(shí)是用戶所關(guān)心的,比如后臺(tái)播放音樂(lè)或網(wǎng)絡(luò)下載數(shù)據(jù)。所以系統(tǒng)保證他們的運(yùn)行,直到不能保證所有的前臺(tái)可見(jiàn)程序都正常運(yùn)行時(shí)才會(huì)終止他們。

          4 一個(gè)后臺(tái)進(jìn)程就是一個(gè)非當(dāng)前正在運(yùn)行的activity(activity的onStop()方法已經(jīng)被調(diào)用),他們不會(huì)對(duì)用戶體驗(yàn)造成直接的影響,當(dāng)沒(méi)有足夠內(nèi)存來(lái)運(yùn)行前臺(tái)可見(jiàn)程序時(shí),他們將會(huì)被終止。通常,后臺(tái)進(jìn)程會(huì)有很多個(gè)在運(yùn)行,所以他們維護(hù)一個(gè)LRU最近使用程序列表來(lái)保證經(jīng)常運(yùn)行的activity能最后一個(gè)被終止。如果一個(gè)activity正確的實(shí)現(xiàn)了生命周期的方法,并且保存它當(dāng)前狀態(tài),殺死這些進(jìn)程將不會(huì)影響到用戶體驗(yàn)。

          5 一個(gè)空線程沒(méi)有運(yùn)行任何可用應(yīng)用程序組,保留他們的唯一原因是為了設(shè)立一個(gè)緩存機(jī)制,來(lái)加快組件啟動(dòng)的時(shí)間。系統(tǒng)經(jīng)常殺死這些內(nèi)存來(lái)平衡系統(tǒng)的整個(gè)系統(tǒng)的資源,進(jìn)程緩存和基本核心緩存之間的資源。
          Android把進(jìn)程里優(yōu)先級(jí)最高的activity或服務(wù),作為這個(gè)進(jìn)程的優(yōu)先級(jí)。例如,一個(gè)進(jìn)程擁有一個(gè)服務(wù)和一個(gè)可見(jiàn)的activity,那么這個(gè)進(jìn)程將會(huì)被定義為可見(jiàn)進(jìn)程,而不是服務(wù)進(jìn)程。

          此外,如果別的進(jìn)程依賴某一個(gè)進(jìn)程的話,那么被依賴的進(jìn)程會(huì)提高優(yōu)先級(jí)。一個(gè)進(jìn)程服務(wù)于另一個(gè)進(jìn)程,那么提供服務(wù)的進(jìn)程不會(huì)低于獲得服務(wù)的進(jìn)程。例如,如果進(jìn)程A的一個(gè)內(nèi)容提供商服務(wù)于進(jìn)程B的一個(gè)客戶端,或者進(jìn)程A的一個(gè)service被進(jìn)程B的一個(gè)組件綁定,那么進(jìn)程A至少擁有和進(jìn)程B一樣的優(yōu)先級(jí),或者更高。

          因?yàn)橐粋€(gè)運(yùn)行服務(wù)的進(jìn)程的優(yōu)先級(jí)高于運(yùn)行后臺(tái)activity的進(jìn)程,一個(gè)activity會(huì)準(zhǔn)備一個(gè)長(zhǎng)時(shí)間運(yùn)行的操作來(lái)啟動(dòng)一個(gè)服務(wù),而不是啟動(dòng)一個(gè)線程–尤其是這個(gè)操作可能會(huì)拖垮這個(gè)activity。例如后臺(tái)播放音樂(lè)的同時(shí),通過(guò)照相機(jī)向服務(wù)器發(fā)送一張照片,啟動(dòng)一個(gè)服務(wù)會(huì)保證這個(gè)操作至少運(yùn)行在service 進(jìn)程的優(yōu)先級(jí)下,無(wú)論這個(gè)activity發(fā)生了什么,廣播接收者應(yīng)該作為一個(gè)空服務(wù)而不是簡(jiǎn)單的把耗時(shí)的操作單獨(dú)放在一個(gè)線程里。 



          參考推薦:

          android service 學(xué)習(xí)

          Android Service生命周期及用法

          Android生命周期之service/Broadcast

          Android BroadcastReceiver 學(xué)習(xí)

          Android之BroadcastReceiver的使用

          Android BroadcastReceiver啟動(dòng)Service 


          Service (android developer)



          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 芮城县| 涿鹿县| 怀仁县| 弥勒县| 丹江口市| 胶南市| 文化| 高邮市| 惠来县| 株洲县| 平武县| 噶尔县| 刚察县| 壶关县| 汤原县| 定襄县| 南和县| 哈巴河县| 定西市| 手游| 通江县| 双流县| 尤溪县| 乳源| 长武县| 于都县| 呼伦贝尔市| 湟中县| 扬中市| 留坝县| 海安县| 洪江市| 神池县| 嵊州市| 老河口市| 柞水县| 张北县| 阿荣旗| 六安市| 恩施市| 贵德县|