23 個重難點突破,帶你吃透 Service 知識點「長達(dá) 1W+ 字」

前言

  • 學(xué) Android 有一段時間了旱函,想必不少人也和我一樣响巢,平時經(jīng)常東學(xué)西湊,感覺知識點有些凌亂難成體系棒妨。所以趁著這幾天忙里偷閑抵乓,把學(xué)的東西歸納下,捋捋思路。

這篇文章主要針對 Service 相關(guān)的知識點灾炭,進(jìn)行詳細(xì)的梳理,祝大家食用愉快颅眶!

文章目錄

文章目錄

方便大家學(xué)習(xí)蜈出,我在 GitHub 建立了 倉庫


第一篇:Service 是什么


Service 是什么

1.1 什么是 Service

什么是 Service
  • Service (服務(wù)) 是一個一種可以在后臺執(zhí)行長時間運行操作而沒有用戶界面的應(yīng)用組件过蹂。
  • 服務(wù)可由其他應(yīng)用組件啟動(如 Activity ),服務(wù)一旦被啟動將在后臺一直運行聚至,即使啟動服務(wù)的組件( Activity )已銷毀也不受影響酷勺。
  • 此外,組件可以綁定到服務(wù)扳躬,以與之進(jìn)行交互脆诉,甚至是執(zhí)行進(jìn)程間通信 ( IPC )。

1.2 Service 通炒遥總是稱之為 “后臺服務(wù)”

Service 通郴魇ぃ總是稱之為 “后臺服務(wù)”
  • 其中 “后臺” 一詞是相對于前臺而言的,具體是指:其本身的運行并不依賴于用戶可視的 UI 界面
  • 因此片择,從實際業(yè)務(wù)需求上來理解潜的,Service 的適用場景應(yīng)該具備以下條件:
  1. 并不依賴于用戶可視的 UI 界面(當(dāng)然,這一條其實也不是絕對的字管,如前臺 Service 就是與 Notification 界面結(jié)合使用的)

  2. 具有較長時間的運行特性

  3. 注意: 是運行在主線程當(dāng)中的

1.3 服務(wù)進(jìn)程

服務(wù)進(jìn)程
  • 服務(wù)進(jìn)程是通過 startService() 方法啟動的進(jìn)程啰挪,但不屬于前臺進(jìn)程和可見進(jìn)程。例如嘲叔,在后臺播放音樂或者在后臺下載就是服務(wù)進(jìn)程亡呵。

  • 系統(tǒng)保持它們運行,除非沒有足夠內(nèi)存來保證所有的前臺進(jìn)程和可視進(jìn)程硫戈。

第二篇:生命周期


生命周期

2.1 Service 的生命周期

  • 我們先來看看 Service 的生命周期 的基本流程
  • 一張聞名遐邇的圖


    Service的生命周期

2.2 開啟 Service 的兩種方式

開啟 Service 的兩種方式

2.2.1 startService()

startService()
  1. 定義一個類繼承 Service

  2. Manifest.xml 文件中配置該 Service

  3. 使用 ContextstartService(intent) 方法開啟服務(wù)锰什。

  4. 使用 ContextstopService(intent) 方法關(guān)閉服務(wù)。

  5. 該啟動方式,app 殺死汁胆、Activity 銷毀沒有任何影響梭姓,服務(wù)不會停止銷毀。

2.2.2 bindService()

bindService()
  1. 創(chuàng)建 BindService 服務(wù)端嫩码,繼承 Service 并在類中誉尖,創(chuàng)建一個實現(xiàn) IBinder 接口的實例對象,并提供公共方法給客戶端( Activity )調(diào)用铸题。

  2. onBinder() 回調(diào)方法返回該 Binder 實例铡恕。

  3. 在客戶端( Activity )中, 從 onServiceConnection() 回調(diào)方法參數(shù)中接收 Binder ,通過 Binder 對象即可訪問 Service 內(nèi)部的數(shù)據(jù)丢间。

  4. manifests 中注冊 BindService , 在客戶端中調(diào)用 bindService() 方法開啟綁定 Service , 調(diào)用 unbindService() 方法注銷解綁 Service 探熔。

  5. 該啟動方式依賴于客戶端生命周期,當(dāng)客戶端 Activity 銷毀時, 沒有調(diào)用 unbindService() 方法 , Service 也會停止銷毀烘挫。

2.3 Service 有哪些啟動方法诀艰,有什么區(qū)別扶镀,怎樣停用 Service

Service 的啟動與綁定
  • Service 的生命周期中薇正,被回調(diào)的方法比 Activity 少一些,只有 onCreate , onStartCommand , onDestroy , onBindonUnbind 宝与。
  • 通常有兩種方式啟動一個 Service , 他們對 Service 生命周期的影響是不一樣的喜滨。

2.3.1 通過 startService

被啟動的服務(wù)的生命周期
  • Service 會經(jīng)歷 onCreateonStartCommand 捉捅,然后處于運行狀態(tài),stopService 的時候調(diào)用 onDestroy
    方法虽风。

如果是調(diào)用者自己直接退出而沒有調(diào)用 stopService 的話棒口,Service 會一直在后臺運行。

2.3.2 通過 bindService

被綁定的服務(wù)的生命周期

Service 會運行 onCreate 辜膝,然后是調(diào)用 onBind 无牵, 這個時候調(diào)用者和 Service 綁定在一起。調(diào)用者退出了厂抖,Srevice 就會調(diào)用 onUnbind -> onDestroyed 方法茎毁。

所謂綁定在一起就共存亡了。調(diào)用者也可以通過調(diào)用 unbindService 方法來停止服務(wù)忱辅,這時候 Srevice 就會調(diào)用 onUnbind -> onDestroyed 方法七蜘。

2.3.3 需要注意的是如果這幾個方法交織在一起的話,會出現(xiàn)什么情況呢墙懂?

被啟動又被綁定的服務(wù)的生命周期
  1. 一個原則是 ServiceonCreate 的方法只會被調(diào)用一次橡卤,就是你無論多少次的 startServicebindServiceService 只被創(chuàng)建一次损搬。

  2. 如果先是 bind 了碧库,那么 start 的時候就直接運行 ServiceonStartCommand 方法柜与,如果先是 start ,那么 bind 的時候就直接運行 onBind 方法嵌灰。

  3. 如果 service 運行期間調(diào)用了 bindService 弄匕,這時候再調(diào)用 stopService 的話,service 是不會調(diào)用 onDestroy 方法的伞鲫,servicestop 不掉了粘茄,只能調(diào)用 UnbindService , service 就會被銷毀

  4. 如果一個 service 通過 startServicestart 之后,多次調(diào)用 startService 的話秕脓,service 會多次調(diào)
    onStartCommand 方法。多次調(diào)用 stopService 的話儒搭,service 只會調(diào)用一次 onDestroyed 方法吠架。

  5. 如果一個 service 通過 bindServicestart 之后,多次調(diào)用 bindService 的話搂鲫,service 只會調(diào)用一次 onBind 方法傍药。多次調(diào)用 unbindService 的話會拋出異常。

第三篇:Service 與 Thread


Service 與 Thread

3.1 Service 和 Thread 的區(qū)別

Service 和 Thread 的區(qū)別

3.1.1 首先第一點定義上

定義上
  1. thread 是程序執(zhí)行的最小單元魂仍,他是分配 cpu 的基本單位安卓系統(tǒng)中拐辽,我們常說的主線程,UI 線程擦酌,也是線程的一種俱诸。當(dāng)然,線程里面還可以執(zhí)行一些耗時的異步操作赊舶。
  2. service 大家記住睁搭,它是安卓中的一種特殊機(jī)制,service 是運行在主線程當(dāng)中的笼平,所以說它不能做耗時操作园骆,它是由系統(tǒng)進(jìn)程托管,其實 service 也是一種輕量級的 IPC 通信寓调,因為 activity 可以和 service 綁定锌唾,可以和 service 進(jìn)行數(shù)據(jù)通信。
  3. 而且有一種情況夺英,activityservice 是處于不同的進(jìn)程當(dāng)中晌涕,所以說它們之間的數(shù)據(jù)通信,要通過 IPC 進(jìn)程間通信的機(jī)制來進(jìn)行操作秋麸。

3.1.2 第二點是在實際開發(fā)的過程當(dāng)中

第二點是在實際開發(fā)的過程當(dāng)中
  1. 在安卓系統(tǒng)當(dāng)中渐排,線程一般指的是工作線程,就是后臺線程灸蟆,做一些耗時操作的線程驯耻,而主線程是一種特殊的線程亲族,它只是負(fù)責(zé)處理一些 UI 線程的繪制,UI 線程里面絕對不能做耗時操作可缚,這里是最基本最重要的一點霎迫。(這是 Thread 在實際開發(fā)過程當(dāng)中的應(yīng)用)
  2. service 是安卓當(dāng)中,四大組件之一帘靡,一般情況下也是運行在主線程當(dāng)中知给,因此 service 也是不可以做耗時操作的,否則系統(tǒng)會報 ANR 異常( ANR 全稱:Application Not Responding )描姚,就是程序無法做出響應(yīng)涩赢。
  3. 如果一定要在 service 里面進(jìn)行耗時操作,一定要記得開啟單獨的線程去做轩勘。

3.1.3 第三點是應(yīng)用場景上

應(yīng)用場景上
  1. 當(dāng)你需要執(zhí)行耗時的網(wǎng)絡(luò)筒扒,或者這種文件數(shù)據(jù)的查詢,以及其它阻塞 UI 線程的時候绊寻,都應(yīng)該使用工作線程花墩,也就是開啟一個子線程的方式。
  2. 這樣才能保證 UI 線程不被占用澄步,而影響用戶體驗冰蘑。
  3. service 來說,我們經(jīng)常需要長時間在后臺運行村缸,而且不需要進(jìn)行交互的情況下才會使用到服務(wù)祠肥,比如說,我們在后臺播放音樂王凑,開啟天氣預(yù)報的統(tǒng)計搪柑,還有一些數(shù)據(jù)的統(tǒng)計等等。

3.2 為什么要用 Service 而不是 Thread

為什么要用 Service 而不是 Thread
  • Thread 的運行是獨立于 Activity 的索烹,也就是當(dāng)一個 Activityfinish 之后工碾,如果沒有主動停止 Thread 或者 Thread 中的 run 沒有執(zhí)行完畢時那么這個線程會一直執(zhí)行下去。
  • 因此這里會出現(xiàn)一個問題:當(dāng) Activityfinish 之后百姓,你不再持有該 Thread 的引用渊额。
  • 另一方面,你沒有辦法在不同的 Activity 中對同一 Thread 進(jìn)行控制垒拢。

3.3 Service 里面是否能執(zhí)行耗時的操作

Service 里面是否能執(zhí)行耗時的操作
  • service 里面不能執(zhí)行耗時的操作(網(wǎng)絡(luò)請求,拷貝數(shù)據(jù)庫,大文件 )

  • Service 不是獨立的進(jìn)程旬迹,也不是獨立的線程,它是依賴于應(yīng)用程序的主線程的求类,也就是說奔垦,在更多時候不建議在 Service 中編寫耗時的邏輯和操作(比如:網(wǎng)絡(luò)請求,拷貝數(shù)據(jù)庫尸疆,大文件)椿猎,否則會引起 ANR 惶岭。

  • 如果想在服務(wù)中執(zhí)行耗時的任務(wù)。有以下解決方案:

  1. service 中開啟一個子線程
new Thread(){}.start();
  1. 可以使用 IntentService 異步管理服務(wù)( 有關(guān) IntentService 的內(nèi)容在后文中給出 )

3.4 Service 是否在 main thread 中執(zhí)行

Service 是否在 main thread 中執(zhí)行
  • 默認(rèn)情況, 如果沒有顯示的指 service 所運行的進(jìn)程, Serviceactivity 是運 行在當(dāng)前 app 所在進(jìn)程的 main thread ( UI 主線程)里面犯眠。
  • ServiceActivity 在同一個線程按灶,對于同一 app 來說默認(rèn)情況下是在同一個線程中的 main Thread ( UI Thread )
  • 特殊情況 ,可以在清單文件配置 service 執(zhí)行所在的進(jìn)程 ,讓 service 在另 外的進(jìn)程中執(zhí)行 Service 不死之身

3.4.1 在 onStartCommand 方法中將 flag 設(shè)置為 START_STICKY ;

<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" >
</service>
return Service.START_STICKY;

3.4.2 在 xml 中設(shè)置了 android:priority

<!--設(shè)置服務(wù)的優(yōu)先級為MAX_VALUE-->
 <service android:name=".MyService"
          android:priority="2147483647"
          >
 </service>

3.4.3 在 onStartCommand 方法中設(shè)置為前臺進(jìn)程

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
  Notification notification = new Notification(R.mipmap.ic_launcher, "服務(wù)正在運行",System.currentTimeMillis());
   Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,notificationIntent,0);
    RemoteViews remoteView = new RemoteViews(this.getPackageName(),R.layout.notification);
    remoteView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);
    remoteView.setTextViewText(R.id.text , "Hello,this message is in a custom expanded view");
    notification.contentView = remoteView;
    notification.contentIntent = pendingIntent;
    startForeground(1, notification);
    return Service.START_STICKY;
}

3.4.4 在 onDestroy 方法中重啟 service

@Override
public void onDestroy() {
    super.onDestroy();
    startService(new Intent(this, MyService.class));
}

3.4.5 用 AlarmManager.setRepeating(…) 方法循環(huán)發(fā)送鬧鐘廣播, 接收的時候調(diào)用 serviceonStartCommand 方法

Intent intent = new Intent(MainActivity.this,MyAlarmReciver.class);
PendingIntent sender = PendingIntent.getBroadcast( MainActivity.this, 0, intent, 0);

// We want the alarm to go off 10 seconds from now.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 1);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
//重復(fù)鬧鐘
/**
 *  @param type
 * @param triggerAtMillis t 鬧鐘的第一次執(zhí)行時間,以毫秒為單位
 * go off, using the appropriate clock (depending on the alarm type).
 * @param intervalMillis 表示兩次鬧鐘執(zhí)行的間隔時間筐咧,也是以毫秒為單位
 * of the alarm.
 * @param operation 綁定了鬧鐘的執(zhí)行動作鸯旁,比如發(fā)送一個廣播、給出提示等等
 */
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 2 * 1000, sender);

3.4.6 目前市場面的很多三方的消息推送 SDK 喚醒 APP , 例如 Jpush

PS: 以上這些方法并不代表著你的 Service 就永生不死了量蕊,只能說是提高了進(jìn)程的優(yōu)先級铺罢。迄今為止我沒有發(fā)現(xiàn)能夠通過常規(guī)方法達(dá)到流氓需求 (通過長按 home 鍵清除都清除不掉) 的方法,目前所有方法都是指通過 Android 的內(nèi)存回收機(jī)制和普通的第三方內(nèi)存清除等手段后仍然保持運行的方法残炮,有些手機(jī)廠商把這些知名的 app 放入了自己的白名單中畏铆,保證了進(jìn)程不死來提高用戶體驗(如微信、QQ 吉殃、陌陌都在小米的白名單中)。如果從白名單中移除楷怒,他們終究還是和普通 app 一樣躲避不了被殺的命運蛋勺。

第四篇:InterService


  • 作為一個老司機(jī),如果連 Interservice 都沒聽說過鸠删,那就有點那個啥了
InterService

4.1 什么是 IntentService

什么是 IntentService
  • IntentServiceService 的子類抱完,比普通的 Service 增加了額外的功能。

  • 我們常用的 Service 存在兩個問題:

  1. Service 不會專門啟動一條單獨的進(jìn)程刃泡,Service 與它所在應(yīng)用位于同一個進(jìn)程中

  2. Service 也不是專門一條新線程巧娱,因此不應(yīng)該在 Service 中直接處理耗時的任務(wù)

4.2 IntentService 的特征

IntentService 的特征
  • 會創(chuàng)建獨立的 worker 線程來處理所有的 Intent 請求

  • 會創(chuàng)建獨立的 worker 線程來處理 onHandleIntent() 方法實現(xiàn)的代碼,無需處理多線程問題

  • 所有請求處理完成后烘贴,IntentService 會自動停止禁添,無需調(diào)用 stopSelf() 方法停止 Service

  • ServiceonBind() 提供默認(rèn)實現(xiàn),返回 null

  • ServiceonStartCommand 提供默認(rèn)實現(xiàn)桨踪,將請求 Intent 添加到隊列中

4.3 Service 和 IntentService 區(qū)別

Service 和 IntentService 區(qū)別

4.3.1 Service 是用于后臺服務(wù)的

Service 是用于后臺服務(wù)的
  1. 當(dāng)應(yīng)用程序被掛到后臺的時候老翘,為了保證應(yīng)用某些組件仍然可以工作而引入了 Service 這個概念
  2. 那么這里面要強(qiáng)調(diào)的是:Service 不是獨立的進(jìn)程,也不是獨立的線程锻离,它是依賴于應(yīng)用程序的主線程的铺峭,也就是說,在更多時候不建議在 Service 中編寫耗時的邏輯和操作汽纠,否則會引起 ANR 卫键。

也就是,service 里面不可以進(jìn)行耗時的操作虱朵。雖然在后臺服務(wù)莉炉。但是也是在主線程里面钓账。

4.3.2 當(dāng)我們編寫的耗時邏輯,不得不被 service 來管理的時候呢袱,就需要引入 IntentService 官扣。

耗時邏輯
  1. IntentService 是繼承 Service 的,那么它包含了 Service 的全部特性羞福,當(dāng)然也包含 service 的生命周期惕蹄。
  2. 那么與 service 不同的是,IntentService 在執(zhí)行 onCreate 操作的時候治专,內(nèi)部開了一個線程卖陵,去你執(zhí)行你的耗時操作。

4.3.3 使用:

使用
  1. 重寫 protected abstract void onHandleIntent(Intent intent)

4.3.4 IntentService 是一個通過 Context.startService(Intent) 啟動可以處理異步請求的 Service

通過 Context.startService(Intent) 啟動
  1. 使用時你只需要繼承 IntentService 和重寫其中的 onHandleIntent(Intent) 方法接收一個 Intent 對象 , 在適當(dāng)?shù)臅r候會停止自己 ( 一般在工作完成的時候 ) 张峰。
  2. 所有的請求的處理都在一個工作線程中完成 , 它們會交替執(zhí)行 ( 但不會阻塞主線程的執(zhí)行 ) 泪蔫,一次只能執(zhí)行一個請求。

4.3.5 是一個基于消息的服務(wù)

是一個基于消息的服務(wù)
  1. 每次啟動該服務(wù)并不是馬上處理你的工作喘批,而是首先會創(chuàng)建對應(yīng)的 Looper 撩荣,Handler 并且在 MessageQueue 中添加的附帶客戶 IntentMessage 對象。
  2. 當(dāng) Looper 發(fā)現(xiàn)有 Message 的時候接著得到 Intent 對象通過在 onHandleIntent((Intent)msg.obj) 中調(diào)用你的處理程序饶深,處理完后即會停止自己的服務(wù)餐曹。
  3. 意思是 Intent 的生命周期跟你的處理的任務(wù)是一致的,所以這個類用下載任務(wù)中非常好敌厘,下載任務(wù)結(jié)束后服務(wù)自身就會結(jié)束退出台猴。

4.3.6 總結(jié) IntentService 的特征有:

總結(jié) IntentService 的特征
  1. 會創(chuàng)建獨立的 worker 線程來處理所有的 Intent 請求;

  2. 會創(chuàng)建獨立的 worker 線程來處理 onHandleIntent() 方法實現(xiàn)的代碼俱两,無需處理多線程問題饱狂;

  3. 所有請求處理完成后,IntentService會自動停止宪彩,無需調(diào)用 stopSelf() 方法停止 Service 休讳;

第五篇:Service 與 Activity


Service 與 Activity

5.1 Activity 怎么和 Service 綁定,怎么在 Activity 中啟動對應(yīng)的 Service

Service 與 Activity
  • Activity 通過 bindService(Intent service, ServiceConnection conn, int flags)Service 進(jìn)行綁定毯焕,當(dāng)綁定成功的時候 Service 會將代理對象通過回調(diào)的形式傳給 conn 衍腥,這樣我們就拿到了 Service 提供的服務(wù)代理對象。

  • Activity 中可以通過 startServicebindService 方法啟動 Service纳猫。一般情況下如果想獲取 Service 的服務(wù)對象那么肯定需要通過 bindService() 方法婆咸,比如音樂播放器,第三方支付等芜辕。

  • 如果僅僅只是為了開啟一個后臺任務(wù)那么可以使用 startService() 方法尚骄。

5.2 說說 Activity 、Intent 侵续、Service 是什么關(guān)系

Activity 倔丈、Intent 憨闰、Service 是什么關(guān)系
  • 他們都是 Android 開發(fā)中使用頻率最高的類。其中 ActivityService 都屬于 Android 的四大組件需五。他倆都是 Context 類的子類 ContextWrapper 的子類鹉动,因此他倆可以算是兄弟關(guān)系吧。

  • 不過他們各有各自的本領(lǐng)宏邮,Activity 負(fù)責(zé)用戶界面的顯示和交互泽示,Service 負(fù)責(zé)后臺任務(wù)的處理。

  • ActivityService 之間可以通過 Intent 傳遞數(shù)據(jù)蜜氨,因此可以把 Intent 看作是通信使者械筛。

5.3 Service 和 Activity 在同一個線程嗎

Service 和 Activity 在同一個線程嗎

對于同一 app 來說默認(rèn)情況下是在同一個線程中的,main ThreadUI Thread )飒炎。

5.4 Service 里面可以彈吐司么

Service 里面可以彈吐司么
  • 可以
  • 彈吐司有個條件是:得有一個 Context 上下文埋哟,而 Service 本身就是 Context 的子類
  • 因此在 Service 里面彈吐司是完全可以的谜诫。比如我們在 Service 中完成下載任務(wù)后可以彈一個吐司通知給用戶罚勾。

5.5 與 Service 交互方式

與 Service 交互方式

5.5.1 廣播交互

廣播交互
  1. Server 端將目前的下載進(jìn)度,通過廣播的方式發(fā)送出來渊涝,Client 端注冊此廣播的監(jiān)聽器煞赢,當(dāng)獲取到該廣播后砍鸠,將廣播中當(dāng)前的下載進(jìn)度解析出來并更新到界面上。
  2. 定義自己的廣播耕驰,這樣在不同的 ActivityService 以及應(yīng)用程序之間录豺,就可以通過廣播來實現(xiàn)交互朦肘。

5.5.2 共享文件交互

共享文件交互
  1. 我們使用 SharedPreferences 來實現(xiàn)共享,當(dāng)然也可以使用其它 IO 方法實現(xiàn)双饥,通過這種方式實現(xiàn)交互時需要注意媒抠,對于文件的讀寫的時候,同一時間只能一方讀一方寫咏花,不能兩方同時寫趴生。
  2. Server 端將當(dāng)前下載進(jìn)度寫入共享文件中,Client 端通過讀取共享文件中的下載進(jìn)度昏翰,并更新到主界面上苍匆。

5.5.3 Messenger 交互 ( 信使交互 )

Messenger 交互 ( 信使交互 )
  1. Messenger 翻譯過來指的是信使,它引用了一個 Handler 對象棚菊,別人能夠向它發(fā)送消息 ( 使用 mMessenger.send ( Message msg ) 方法)浸踩。
  2. 該類允許跨進(jìn)程間基于 Message 通信,在服務(wù)端使用 Handler 創(chuàng)建一個 Messenger 统求,客戶端只要獲得這個服務(wù)端的 Messenger 對象就可以與服務(wù)端通信了
  3. Server 端與 Client 端之間通過一個 Messenger 對象來傳遞消息检碗,該對象類似于信息中轉(zhuǎn)站据块,所有信息通過該對象攜帶

5.5.4 自定義接口交互

自定義接口交互
  1. 其實就是我們自己通過接口的實現(xiàn)來達(dá)到 ActivityService 交互的目的,我們通過在 ActivityService 之間架設(shè)一座橋樑折剃,從而達(dá)到數(shù)據(jù)交互的目的另假,而這種實現(xiàn)方式和 AIDL 非常類似
  2. 自定義一個接口,該接口中有一個獲取當(dāng)前下載進(jìn)度的空方法怕犁。Server 端用一個類繼承自 Binder 并實現(xiàn)該接口边篮,覆寫了其中獲取當(dāng)前下載進(jìn)度的方法。Client 端通過 ServiceConnection 獲取到該類的對象因苹,從而能夠使用該獲取當(dāng)前下載進(jìn)度的方法苟耻,最終實現(xiàn)實時交互。

5.5.5 AIDL 交互

AIDL交互
  1. 遠(yuǎn)程服務(wù)一般通過 AIDL 來實現(xiàn)扶檐,可以進(jìn)行進(jìn)程間通信凶杖,這種服務(wù)也就是遠(yuǎn)程服務(wù)。
  2. AIDL 屬于 AndroidIPC 機(jī)制款筑,常用于跨進(jìn)程通信智蝠,主要實現(xiàn)原理基于底層 Binder 機(jī)制。

第六篇:使用


使用

6.1 什么情況下會使用 Service

什么情況下會使用 Service

6.1.1 經(jīng)驗總結(jié):

經(jīng)驗總結(jié)
  1. Service 其實就是背地搞事情杈湾,又不想讓別人知道
  2. 舉一個生活當(dāng)中的例子,你想知道一件事情不需要直接去問攘须,你可以通過側(cè)面了解漆撞。這就是 Service 設(shè)計的初衷

6.1.2 Service 為什么被設(shè)計出來

Service 為什么被設(shè)計出來
  1. 根據(jù) Service 的定義,我們可以知道需要長期在后臺進(jìn)行的工作我們需要將其放在 Service 中去做于宙。
  2. 得再通熟易懂一點浮驳,就是不能放在 Activity 中來執(zhí)行的工作就必須得放到 Service 中去做。
  3. 如:音樂播放捞魁、下載至会、上傳大文件、定時關(guān)閉應(yīng)用等功能谱俭。這些功能如果放到 Activity 中做的話奉件,那么 Activity 退出被銷毀了的話,那這些功能也就停止了昆著,這顯然是不符合我們的設(shè)計要求的县貌,所以要將他們放在 Service 中去執(zhí)行。

6.2 onStartCommand() 返回值 int 值的區(qū)別

  • 有四種返回值,不同值代表的意思如下:
onStartCommand() 返回值 int 值的區(qū)別

6.2.1 START_STICKY :

  1. 如果 service 進(jìn)程被 kill 掉,保留 service 的狀態(tài)為開始狀態(tài),但不保留遞送的 intent 對象凑懂。
  2. 隨后系統(tǒng)會嘗試重新創(chuàng)建 service, 由于服務(wù)狀態(tài)為開始狀態(tài),所以創(chuàng)建服務(wù)后一定會調(diào)用 onStartCommand ( Intent, int, int ) 方法窃这。
  3. 如果在此期間沒有任何啟動命令被傳遞到 service , 那么參數(shù) Intent 將為 null

6.2.2 START_NOT_STICKY :

  1. “非粘性的”。
  2. 使用這個返回值時 , 如果在執(zhí)行完 onStartCommand 后 , 服務(wù)被異常 kill 掉 杭攻,系統(tǒng)不會自動重啟該服務(wù)祟敛。

6.2.3 START_REDELIVER_INTENT:

  1. 重傳 Intent
  2. 使用這個返回值時,如果在執(zhí)行完 onStartCommand 后,服務(wù)被異常 kill 掉
  3. 系統(tǒng)會自動重啟該服務(wù) , 并將 Intent 的值傳入兆解。

6.2.4 START_STICKY_COMPATIBILITY:

  1. START_STICKY 的兼容版本 , 但不保證服務(wù)被 kill 后一定能重啟馆铁。

6.3 在 service 的生命周期方法 onstartConmand() 可不可以執(zhí)行網(wǎng)絡(luò)操作?如何在 service 中執(zhí)行網(wǎng)絡(luò)操作锅睛?

onstartConmand() 可不可以執(zhí)行網(wǎng)絡(luò)操作埠巨?如何在 service 中執(zhí)行網(wǎng)絡(luò)操作?
  • 可以直接在 Service 中執(zhí)行網(wǎng)絡(luò)操作
  • onStartCommand() 方法中可以執(zhí)行網(wǎng)絡(luò)操作

6.4 提高 service 的優(yōu)先級

提高 service 的優(yōu)先級
  • AndroidManifest.xml 文件中對于 intent-filter 可以通過 android:priority = “1000” 這個屬性設(shè)置最高優(yōu)先級现拒,1000 是最高值辣垒,如果數(shù)字越小則優(yōu)先級越低,同時實用于廣播印蔬。

  • onStartCommand 里面調(diào)用 startForeground() 方法把 Service 提升為前臺進(jìn)程級別勋桶,然后再 onDestroy 里面要記得調(diào)用 stopForeground () 方法。

  • onStartCommand 方法侥猬,手動返回 START_STICKY 例驹。

廣播
  • onDestroy 方法里發(fā)廣播重啟 service
  1. service + broadcast 方式退唠,就是當(dāng) serviceondestory 的時候鹃锈,發(fā)送一個自定義的廣播
  2. 當(dāng)收到廣播的時候,重新啟動 service 瞧预。( 第三方應(yīng)用或是在 setting 里-應(yīng)用強(qiáng)制停止時屎债,APP 進(jìn)程就直接被干掉了,onDestroy 方法都進(jìn)不來垢油,所以無法保證會執(zhí)行 )
  • 監(jiān)聽系統(tǒng)廣播判斷 Service 狀態(tài)扔茅。
  1. 通過系統(tǒng)的一些廣播
  2. 比如:手機(jī)重啟、界面喚醒秸苗、應(yīng)用狀態(tài)改變等等監(jiān)聽并捕獲到,然后判斷我們的 Service 是否還存活运褪。
  • Application 加上 Persistent 屬性惊楼。

6.5 Service 的 onRebind ( Intent ) 方法在什么情況下會執(zhí)行

onRebind ( Intent ) 方法在什么情況下會執(zhí)行
  • 如果在 onUnbind() 方法返回 true 的情況下會執(zhí)行 , 否則不執(zhí)行。

總結(jié)


  1. 本文基本涵蓋了 Android Service 相關(guān)的知識點秸讹。由于篇幅原因檀咙,諸如 InterService 具體使用方法等,沒辦法詳細(xì)的介紹璃诀,大家很容易就能在網(wǎng)上找到資料進(jìn)行學(xué)習(xí)弧可。
  2. 重點:關(guān)于 Android 的四大組件,到現(xiàn)在為止我才總結(jié)完 ActivityService劣欢,我將繼續(xù)針對棕诵,BroadcastRecevier ContentProvider 等裁良,以及四大組件之外的,事件分發(fā)校套、滑動沖突价脾、新能優(yōu)化等重要模塊,進(jìn)行全面總結(jié)笛匙,歡迎大家關(guān)注 _yuanhao 的 簡書侨把,方便及時接收更新
  3. 開始前還以為總結(jié)不難,實際寫文章的過程中妹孙,才知道什么是艱辛秋柄。也不知道自己能不能咬牙堅持下去,希望大家給我鼓勵蠢正,就算只是一個贊骇笔,也是我堅持下去的理由!

碼字不易机隙,你的點贊是我總結(jié)的最大動力蜘拉!


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚁堤,一起剝皮案震驚了整個濱河市醉者,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖撬即,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件立磁,死亡現(xiàn)場離奇詭異,居然都是意外死亡搞莺,警方通過查閱死者的電腦和手機(jī)息罗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來才沧,“玉大人迈喉,你說我怎么就攤上這事∥略玻” “怎么了挨摸?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長岁歉。 經(jīng)常有香客問我得运,道長,這世上最難降的妖魔是什么锅移? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任熔掺,我火速辦了婚禮,結(jié)果婚禮上非剃,老公的妹妹穿的比我還像新娘置逻。我一直安慰自己,他們只是感情好备绽,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布券坞。 她就那樣靜靜地躺著,像睡著了一般肺素。 火紅的嫁衣襯著肌膚如雪恨锚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天倍靡,我揣著相機(jī)與錄音猴伶,去河邊找鬼。 笑死塌西,一個胖子當(dāng)著我的面吹牛他挎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雨让,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼忿等!你這毒婦竟也來了栖忠?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎庵寞,沒想到半個月后狸相,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡捐川,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年脓鹃,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片古沥。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘸右,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岩齿,到底是詐尸還是另有隱情太颤,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布盹沈,位于F島的核電站龄章,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏乞封。R本人自食惡果不足惜做裙,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肃晚。 院中可真熱鬧锚贱,春花似錦、人聲如沸陷揪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悍缠。三九已至卦绣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間飞蚓,已是汗流浹背滤港。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留趴拧,地道東北人溅漾。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像著榴,于是被迫代替她去往敵國和親添履。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

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