Service - JobIntentService

一、Service、IntentService、JobIntentService的區(qū)別

  • Service: 它用于執(zhí)行某些后臺操作的任務,它在主線程上運行,這也是它的缺點。對于主線程上發(fā)生的任何長時間運行的操作,建議創(chuàng)建一個新線程并執(zhí)行該任務(例如; Handler )不會影響主線程的性能。
  • IntentService : 也是用來完成一些長時間運行的后臺任務。唯一的區(qū)別是, 它創(chuàng)建一個新線程來執(zhí)行此任務, 而不在主線程上運行。那么缺點就是: 當應用程序被終止時,提供給IntentService的作業(yè)將丟失。

  • JobIntentService : 與IntentService非常相似, 但JobIntentService是不需要通過startService啟動, 而是靜態(tài)啟動的,而且,一旦應用程序重新創(chuàng)建/啟動,它可以從頭開始啟動作業(yè)。這句話還需要再考究一下。

從Oreo(Android 8.0)之后, 如果應用程序在后臺運行, 則不允許在后臺啟動服務。Android要求我們通過 content.startForegroundService 而不是 context.startService來啟動服務。并且在服務啟動后的5s之內, 必須將其綁定到通知, 以使UI元素與之關聯(lián),否則就會報錯:

android.app.RemoteServiceException
Context.startForegroundService() did not then call Service.startForeground()

那么, 既然知道了原理,是不是直接調用 startForeground(int id, Notification notification) 方法就可以了?

答案是否定的??!

如果IntentService 在啟動后(從onStartCommand返回了)被系統(tǒng)殺掉了,在下一次調用Context.startService()之前,不會再創(chuàng)建Service。期間,也不接受空Intent參數(shù)的onStartCommand方法調用,因為空的Intent無法進行Service的創(chuàng)建,所以也就未執(zhí)行IntentService的onCreate、onStart、onHandleIntent方法中的startForeground方法,最后報出以上異常。

所以為了絕對規(guī)避這個異常,使用JobIntentService替代IntentService還是可以的,至于為什么??因為它是通過靜態(tài)方法啟動的, 無關乎生命周期,不需要在5s之內調用 startForeground(int id, Notification notification)。

//InitIntentService為JobIntentService子類名稱
InitIntentService.enqueueWork(context, new Intent());

?
?

二、JobIntentService和JobService的對比

先看一下JobIntentService的官方文檔:

Helper for processing work that has been enqueued for a job/service. When running on {@link android.os.Build.VERSION_CODES#O Android O} or later, the work will be dispatched as a job via {@link android.app.job.JobScheduler#enqueue JobScheduler.enqueue}. When running on older versions of the platform, it will use {@link android.content.Context#startService Context.startService}.

官方文檔解釋為,用于處理被加入到job或service任務的一個輔助工具,8.0以下被當作普通的Intent使用startSerivce()啟動service來執(zhí)行。

8.0以上任務被作為job用jobScheduler.enqueue()方法來分發(fā),說到Jobscheduler,應該不陌生了,框架提供的用來APP調度任務的接口,根據(jù)APP要求構建JobInfo,系統(tǒng)會在適當?shù)臅r間調用JobInfo指定的JobService來執(zhí)行你的任務。

所以在Android8.0及以上JobIntentService和JobService做的事情是相同的,都是等著JobScheduler分配任務來執(zhí)行。

不同點在于,JobService使用的handler是主線程的Looper,因此需要在onStartJob()中手動創(chuàng)建AsyncTask去執(zhí)行耗時任務,而JobIntentService則幫我們處理這一過程,使用它只需要寫需要做的任務邏輯即可,不用關心卡住主線程的問題。另外,向JobScheduler傳遞任務操作也更簡單了,不需要在指定JobInfo中的參數(shù),直接enqueue(context,intent)就可以。

這有點像Service和IntentService的關系。

?

三、JobIntentService的使用

1、在Manifest中聲名Permission

<uses-permission android:name="android.permission.WAKE_LOCK" />

2、在Manifest中聲名Service

<service android:name=".InitIntentService" 
    android:permission="android.permission.BIND_JOB_SERVICE" />

3、繼承JobIntentService類

public class InitIntentService extends JobIntentService {

    public static final int JOB_ID = 1;

    public static void enqueueWork(Context context, Intent work) {
        enqueueWork(context, InitIntentService.class, JOB_ID, work);
    }

    @Override
    protected void onHandleWork(@NonNull Intent intent) {
        // 具體邏輯
    }
}

4、啟動JobIntentService子類

InitIntentService.enqueueWork(context, new Intent());

JobIntentService不需要關心JobIntentService的生命周期,不需要startService()方法,也就避免了開頭中的crash問題,通過靜態(tài)方法就可以啟動,還是非常不錯的。

?
?
?
?
?
?

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容