Android Service基礎(chǔ)知識(shí)

Service 作為android 四大組件之一丐怯,主要用于再后臺(tái)處理一些耗時(shí)的邏輯或者去執(zhí)行一些長(zhǎng)期運(yùn)行的任務(wù)。

一等脂、startService 和 bindService

1. 生命周期和啟動(dòng)方式:

service_lifecycle.png

1.1 啟動(dòng)
通過startService啟動(dòng)服務(wù)時(shí)娄帖,如果是第一次啟動(dòng),會(huì)調(diào)用onCreate->onStartCommand茫船,但是多次啟動(dòng)時(shí)不會(huì)再調(diào)用onCreate,只有onStartCommand會(huì)被調(diào)用多次扭屁。
通過bindService綁定服務(wù)時(shí)算谈,如果服務(wù)還未啟動(dòng),會(huì)調(diào)用onCreate->onBind料滥,創(chuàng)建并且綁定服務(wù)濒生,多次調(diào)用bindService并不會(huì)多次調(diào)用onBind(),除非是多個(gè)客戶端來綁定服務(wù)幔欧。

1.2 銷毀
如果組件通過調(diào)用 startService() 啟動(dòng)服務(wù)罪治,則服務(wù)將一直運(yùn)行,直到服務(wù)使用 stopSelf()自行停止運(yùn)行礁蔗,或由其他組件通過調(diào)用 stopService() 停止它為止觉义。無(wú)論服務(wù)被啟動(dòng)了多少次,只要調(diào)用一次stopService浴井,便可終止(不考慮被綁定過的情況)晒骇。

如果組件是通過調(diào)用 bindService()來創(chuàng)建服務(wù)(且未調(diào)用onStartCommand()),則服務(wù)只會(huì)在該組件與其綁定時(shí)運(yùn)行磺浙。一旦該服務(wù)與所有客戶端之間的綁定全部取消洪囤,系統(tǒng)便會(huì)銷毀它。

2. starService和bindService一起使用:

如果一個(gè)Service又被啟動(dòng)又被綁定撕氧,則該Service會(huì)一直在后臺(tái)運(yùn)行瘤缩。首先不管如何調(diào)用,onCreate始終只會(huì)調(diào)用一次伦泥。startService調(diào)用多少次剥啤,Service的onStartCommand方法便會(huì)調(diào)用多少次锦溪。Service的終止,需要unbindService和stopService同時(shí)調(diào)用才行府怯。不管startService與bindService的調(diào)用順序刻诊,如果先調(diào)用unbindService,此時(shí)服務(wù)不會(huì)自動(dòng)終止牺丙,再調(diào)用stopService之后则涯,服務(wù)才會(huì)終止;如果先調(diào)用stopService冲簿,此時(shí)服務(wù)也不會(huì)終止是整,再次調(diào)用unbindService或者之前調(diào)用bindService的Context不存在了 ,服務(wù)才會(huì)停止民假。

3. 使用場(chǎng)景:

startService 主要用于開啟服務(wù),例如后臺(tái)下載和播放音樂
bindService 主要為了使用服務(wù)中的一些功能或者與服務(wù)進(jìn)行交互
這2種模式不是完全分離的龙优。你可以可以綁定到一個(gè)通過startService()啟動(dòng)的服務(wù)羊异。如一個(gè)intent想要播放音樂,通過startService啟動(dòng)后臺(tái)播放音樂的service彤断。然后野舶,也許用戶想要操作播放器或者獲取當(dāng)前正在播放的樂曲的信息,一個(gè)activity就會(huì)通過bindService建立一個(gè)到此service的連接. 這種情況下 stopService() 在全部的連接關(guān)閉后才會(huì)真正停止service宰衙。

Tips:

  1. 服務(wù)的onCreate和onDestroy在一個(gè)生命周期中只會(huì)執(zhí)行一次
  2. service的stopself方法的功能是平道,當(dāng)完成所有功能之后,將service停掉
  3. Service中onRebind方法被調(diào)用的時(shí)機(jī)供炼,需要滿足2個(gè)條件:
    (1)服務(wù)中onUnBind方法返回值為true
    (2)服務(wù)對(duì)象被解綁后沒有被銷毀一屋,之后再次被綁定

2. onStartCommand的返回值:

請(qǐng)注意,onStartCommand() 方法必須返回整型數(shù)袋哼。整型數(shù)是一個(gè)值冀墨,用于描述系統(tǒng)應(yīng)該如何在服務(wù)終止的情況下繼續(xù)運(yùn)行服務(wù)(如上所述,IntentService 的默認(rèn)實(shí)現(xiàn)將為您處理這種情況涛贯,不過您可以對(duì)其進(jìn)行修改)诽嘉。從onStartCommand()返回的值必須是以下常量之一:

1. START_NOT_STICKY

如果系統(tǒng)在 onStartCommand() 返回后終止服務(wù),則除非有掛起 Intent 要傳遞弟翘,否則系統(tǒng)不會(huì)重建服務(wù)虫腋。這是最安全的選項(xiàng),可以避免在不必要時(shí)以及應(yīng)用能夠輕松重啟所有未完成的作業(yè)時(shí)運(yùn)行服務(wù)稀余。

2. START_STICKY

如果系統(tǒng)在 onStartCommand() 返回后終止服務(wù)悦冀,則會(huì)重建服務(wù)并調(diào)用 onStartCommand(),但不會(huì)重新傳遞最后一個(gè) Intent睛琳。相反雏门,除非有掛起 Intent 要啟動(dòng)服務(wù)(在這種情況下嘿歌,將傳遞這些 Intent ),否則系統(tǒng)會(huì)通過空 Intent 調(diào)用 onStartCommand()茁影。這適用于不執(zhí)行命令宙帝、但無(wú)限期運(yùn)行并等待作業(yè)的媒體播放器(或類似服務(wù))。

3. START_REDELIVER_INTENT

如果系統(tǒng)在 onStartCommand() 返回后終止服務(wù)募闲,則會(huì)重建服務(wù)步脓,并通過傳遞給服務(wù)的最后一個(gè) Intent 調(diào)用 onStartCommand()。任何掛起 Intent 均依次傳遞浩螺。這適用于主動(dòng)執(zhí)行應(yīng)該立即恢復(fù)的作業(yè)(例如下載文件)的服務(wù)靴患。

二、前臺(tái)服務(wù)

Service幾乎都是在后臺(tái)運(yùn)行的要出,一直以來它都是默默地做著辛苦的工作鸳君。但是Service的系統(tǒng)優(yōu)先級(jí)還是比較低的,當(dāng)系統(tǒng)出現(xiàn)內(nèi)存不足情況時(shí)患蹂,就有可能會(huì)回收掉正在后臺(tái)運(yùn)行的Service或颊。如果你希望Service可以一直保持運(yùn)行狀態(tài),而不會(huì)由于系統(tǒng)內(nèi)存不足的原因?qū)е卤换厥沾冢涂梢钥紤]使用前臺(tái)Service囱挑。前臺(tái)Service和普通Service最大的區(qū)別就在于,它會(huì)一直有一個(gè)正在運(yùn)行的圖標(biāo)在系統(tǒng)的狀態(tài)欄顯示沼溜,下拉狀態(tài)欄后可以看到更加詳細(xì)的信息平挑,非常類似于通知的效果。當(dāng)然有時(shí)候你也可能不僅僅是為了防止Service被回收才使用前臺(tái)Service系草,有些項(xiàng)目由于特殊的需求會(huì)要求必須使用前臺(tái)Service通熄,比如說墨跡天氣。

    Intent intent = new Intent(this, MainActivity.class);
    //需要讓Activity運(yùn)行在新的任務(wù)棧中
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    Notification.Builder builder = new Notification.Builder(this);
    Notification notification = builder.setSmallIcon(R.mipmap.ic_launcher)
            .setContentText("this is a notify")
            .setContentTitle("notify!!!").setTicker("notify")
            .setContentIntent(PendingIntent.
                    getActivity(ServiceB.this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT))
            .build();
    startForeground(1, notification);

Tips:

  1. startForeground讓服務(wù)變成前臺(tái)服務(wù)并顯示通知找都,這時(shí)必須要setSmallIcon棠隐,否則會(huì)顯示默認(rèn)的通知,不顯示自定義通知
  2. 如何讓服務(wù)一直存活 http://zhoujianghua.com/2015/07/28/black_technology_in_alipay/

三檐嚣、Service 和 Thread

之所以有不少人會(huì)把它們聯(lián)系起來助泽,主要就是因?yàn)镾ervice的后臺(tái)概念。Thread我們大家都知道嚎京,是用于開啟一個(gè)子線程嗡贺,在這里去執(zhí)行一些耗時(shí)操作就不會(huì)阻塞主線程的運(yùn)行。而Service我們最初理解的時(shí)候鞍帝,總會(huì)覺得它是用來處理一些后臺(tái)任務(wù)的诫睬,一些比較耗時(shí)的操作也可以放在這里運(yùn)行,這就會(huì)讓人產(chǎn)生混淆了帕涌。但其實(shí)Service其實(shí)是運(yùn)行在主線程里的摄凡,所以說service的主進(jìn)程中不能執(zhí)行耗時(shí)的任務(wù)续徽,需要另外啟動(dòng)線程執(zhí)行,例如IntentService的內(nèi)部就是使用了HandlerThread的實(shí)現(xiàn)亲澡。

四钦扭、IntentService

IntentService是Service 的子類,它使用工作線程逐一處理所有啟動(dòng)請(qǐng)求床绪。如果不要求服務(wù)同時(shí)處理多個(gè)請(qǐng)求客情,這是最好的選擇。只需實(shí)現(xiàn) onHandleIntent() 方法即可癞己,該方法會(huì)接收每個(gè)啟動(dòng)請(qǐng)求的Intent膀斋,能夠執(zhí)行后臺(tái)工作。由于大多數(shù)啟動(dòng)服務(wù)都不必同時(shí)處理多個(gè)請(qǐng)求痹雅,因此使用 IntentService 類實(shí)現(xiàn)服務(wù)也許是最好的選擇仰担。

IntentService的特點(diǎn):

  1. IntentService 會(huì)創(chuàng)建一個(gè)線程,來處理所有傳給onStartCommand()的Intent請(qǐng)求
  2. 創(chuàng)建一個(gè)請(qǐng)求隊(duì)列绩社,用于將 Intent 逐一傳遞給 onHandleIntent() 實(shí)現(xiàn)摔蓝,不必?fù)?dān)心多線程問題
  3. 在所有的請(qǐng)求執(zhí)行完畢后結(jié)束Service
  4. 提供 onBind() 的默認(rèn)實(shí)現(xiàn)(返回 null)
  5. 提供默認(rèn)的 onStartCommand() 實(shí)現(xiàn),將intent傳入等待隊(duì)列中铃将,然后到onHandleIntent()的實(shí)現(xiàn)。所以如果需要重寫onStartCommand() 方法一定要調(diào)用父類的實(shí)現(xiàn)哑梳。

Tips:

  1. IntentService是針對(duì)StarteService設(shè)計(jì)的劲阎,由于它默認(rèn)實(shí)現(xiàn)的onBind()方法返回值是null,所以不適合bindService()
  2. 多次startService請(qǐng)求執(zhí)行耗時(shí)任務(wù)鸠真,不會(huì)并發(fā)執(zhí)行onHandleIntent()方法悯仙,而是一個(gè)一個(gè)順序執(zhí)行。當(dāng)所有的任務(wù)執(zhí)行完成吠卷,IntentService會(huì)自動(dòng)銷毀

問題:onStartCommand的返回值的具體應(yīng)用場(chǎng)景锡垄?

Demo:
http://download.csdn.net/detail/time_traveller14/9886836

參考資料:
https://developer.android.com/guide/components/services.html
http://blog.csdn.net/guolin_blog/article/details/11952435

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市祭隔,隨后出現(xiàn)的幾起案子货岭,更是在濱河造成了極大的恐慌,老刑警劉巖疾渴,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件千贯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡搞坝,警方通過查閱死者的電腦和手機(jī)搔谴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桩撮,“玉大人敦第,你說我怎么就攤上這事峰弹。” “怎么了芜果?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵鞠呈,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我师幕,道長(zhǎng)粟按,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任霹粥,我火速辦了婚禮灭将,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘后控。我一直安慰自己庙曙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布浩淘。 她就那樣靜靜地躺著捌朴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪张抄。 梳的紋絲不亂的頭發(fā)上砂蔽,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音署惯,去河邊找鬼左驾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛极谊,可吹牛的內(nèi)容都是我干的诡右。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼轻猖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼帆吻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起咙边,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤猜煮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后败许,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體友瘤,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年檐束,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了辫秧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡被丧,死狀恐怖盟戏,靈堂內(nèi)的尸體忽然破棺而出绪妹,到底是詐尸還是另有隱情,我是刑警寧澤柿究,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布邮旷,位于F島的核電站,受9級(jí)特大地震影響蝇摸,放射性物質(zhì)發(fā)生泄漏婶肩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一貌夕、第九天 我趴在偏房一處隱蔽的房頂上張望律歼。 院中可真熱鬧,春花似錦啡专、人聲如沸险毁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)畔况。三九已至,卻和暖如春慧库,著一層夾襖步出監(jiān)牢的瞬間跷跪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工齐板, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吵瞻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓覆积,卻偏偏與公主長(zhǎng)得像听皿,于是被迫代替她去往敵國(guó)和親熟呛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宽档,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 前言:本文所寫的是博主的個(gè)人見解,如有錯(cuò)誤或者不恰當(dāng)之處庵朝,歡迎私信博主吗冤,加以改正!原文鏈接九府,demo鏈接 Serv...
    PassersHowe閱讀 1,403評(píng)論 0 5
  • 服務(wù)基本上分為兩種形式 啟動(dòng) 當(dāng)應(yīng)用組件(如 Activity)通過調(diào)用 startService() 啟動(dòng)服務(wù)時(shí)...
    pifoo閱讀 1,254評(píng)論 0 8
  • [文章內(nèi)容來自Developers] Service是一個(gè)可以在后臺(tái)執(zhí)行長(zhǎng)時(shí)間運(yùn)行操作而不提供用戶界面的應(yīng)用組件椎瘟。...
    岳小川閱讀 857評(píng)論 0 7
  • 轉(zhuǎn)載注明出處:http://www.reibang.com/p/a1d3d9693e91 1. 簡(jiǎn)介 與前一篇An...
    王三的貓阿德閱讀 1,902評(píng)論 1 9
  • 描述 給出一棵二叉樹,返回其節(jié)點(diǎn)值從底向上的層次序遍歷(按從葉節(jié)點(diǎn)所在層到根節(jié)點(diǎn)所在的層遍歷侄旬,然后逐層從左往右遍歷...
    6默默Welsh閱讀 505評(píng)論 0 1