應(yīng)用退出后繼續(xù)運(yùn)行后臺任務(wù),來試試WorkManager吧较木!

什么是WorkManager

WorkManagerJetpack中的一個庫红符,它擴(kuò)展了JobScheduler的能力, 提供給應(yīng)用在后臺執(zhí)行任務(wù)的能力伐债。

它能幫助應(yīng)用在滿足條件的時候執(zhí)行后臺任務(wù)预侯,不管應(yīng)用進(jìn)程是否存活。

一般滿足如下條件的任務(wù)適合使用WorkManager執(zhí)行:

  • 即使應(yīng)用被退出峰锁,也要保證執(zhí)行的任務(wù)
  • 可推遲的任務(wù)
  • 定期執(zhí)行的任務(wù)

WorkManager怎么使用

1. 引入相關(guān)庫

dependencies {
    def work_version = "2.8.0"

    // (Java only)
    implementation "androidx.work:work-runtime:$work_version"

    // Kotlin + coroutines
    implementation "androidx.work:work-runtime-ktx:$work_version"

    // optional - RxJava2 support
    implementation "androidx.work:work-rxjava2:$work_version"

    // optional - GCMNetworkManager support
    implementation "androidx.work:work-gcm:$work_version"

    // optional - Test helpers
    androidTestImplementation "androidx.work:work-testing:$work_version"

    // optional - Multiprocess support
    implementation "androidx.work:work-multiprocess:$work_version"
}

WorkManager庫目前更新到2.8.0版本萎馅,讀者在使用的時候,可以去WorkManagerAPI參考文檔上找到當(dāng)前的最新版本虹蒋。

2. 定義一個Worker


public class UploadWorker extends Worker {
   public UploadWorker(@NonNull Context context, @NonNull WorkerParameters params) {
       super(context, params);
   }

   @Override
   public Result doWork() {
     // Do the work here--in this case, upload the images.
     uploadImages();

     // Indicate whether the work finished successfully with the Result
     return Result.success();
   }
}

初始化一個執(zhí)行任務(wù)的UploadWorker糜芳,繼承自Worker類,在doWork中執(zhí)行相應(yīng)的任務(wù)魄衅。

doWork的返回結(jié)果:

  • Result.success(): 工作成功完成
  • Result.failure(): 工作失敗
  • Result.retry(): 工作失敗峭竣,應(yīng)根據(jù)重試策略在其他時間嘗試

3. 創(chuàng)建WorkRequest

創(chuàng)建完Worker之后,你需要告訴系統(tǒng)晃虫,你的任務(wù)想什么時候執(zhí)行皆撩,按照什么策略執(zhí)行。

1)一次性工作

WorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class)
       // Additional configuration
       .build();
  1. 加急工作

2.7.0之后的版本引入了加急工作的概念哲银,執(zhí)行一些重要的任務(wù)可以設(shè)置加急處理毅访。

OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
    .setInputData(inputData)
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build();

加急處理的worker沮榜,在Android12之前通過前臺服務(wù)實(shí)現(xiàn),會在通知欄上顯示通知喻粹,所以必須實(shí)現(xiàn)getForegroundInfo方法蟆融。

不過加急任務(wù)并不一定會立刻執(zhí)行,在某些情況下守呜,可能還是會延遲啟動:

  • 系統(tǒng)負(fù)載過高:當(dāng)系統(tǒng)內(nèi)存等資源不足時
  • 超出加急作業(yè)配額限制

3)定期工作

PeriodicWorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
           // Constraints
           .build();

4. 創(chuàng)建約束條件

只有滿足約束條件型酥,才會執(zhí)行任務(wù)。如果在執(zhí)行過程中查乒,不再滿足某個約束弥喉,WorkManager會停止工作。

Constraints constraints = new Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .setRequiresCharging(true)
       .build();

5. 提交WorkRequest

WorkManager
    .getInstance(myContext)
    .enqueue(uploadWorkRequest);

使用enqueueWorkManager任務(wù)提交給系統(tǒng)玛迄。

多進(jìn)程WorkManager

WorkManager 2.6版本開始由境,支持多進(jìn)程的使用場景”鸵椋可以在一個進(jìn)程中設(shè)置服務(wù)虏杰,讓服務(wù)在另一個進(jìn)程中被調(diào)度。

1)設(shè)置WorkRequest

           val serviceName = RemoteWorkerService::class.java.name
            val componentName = ComponentName(PACKAGE_NAME, serviceName)
            val oneTimeWorkRequest = buildOneTimeWorkRemoteWorkRequest(
                componentName,
                ExampleRemoteCoroutineWorker::class.java
            )

            workManager?.enqueue(oneTimeWorkRequest)

2)在Manifest中定義RemoteWorkService

        <service
            android:name="androidx.work.multiprocess.RemoteWorkerService"
            android:exported="false"
            android:process=":worker1" />

RemoteWorkerService不需要自己創(chuàng)建勒虾,但是需要在Manifest里指定所運(yùn)行的進(jìn)程名纺阔。

也可以定義自己的Service,需要繼承自RemoteWorkService修然。

3)Java繼承RemoteListanableWorker

Java:

public class ExampleRemoteListenableWorker extends RemoteListenableWorker {

    private static final String TAG = "ListenableWorker";

    public ExampleRemoteListenableWorker(Context appContext, WorkerParameters workerParams) {
        super(appContext, workerParams);
    }

    @Override
    public ListenableFuture<Result> startRemoteWork() {
        return CallbackToFutureAdapter.getFuture(completer -> {
            Log.i(TAG, "Starting ExampleRemoteListenableWorker");

            // Do some work here.

            return completer.set(Result.success());
        });
    }
}

4) Kotlin繼承RemoteCoroutineWorker
Kotlin:

class ExampleRemoteCoroutineWorker(context: Context, parameters: WorkerParameters) :
    RemoteCoroutineWorker(context, parameters) {

    override suspend fun doRemoteWork(): Result {

        Log.d(TAG, "Starting ExampleRemoteCoroutineWorker")

        // Do some work here

        return Result.success()
    }

    companion object {
        private const val TAG = "CoroutineWorker"
    }
}

總結(jié)

本篇文章介紹了WorkManager的使用方法笛钝,包括如何在多進(jìn)程中使用WorkManager

WorkManager使用在后臺運(yùn)行的任務(wù)愕宋,即使App掛掉了玻靡,也要保證能完成的任務(wù),或者是一些定時任務(wù)中贝。

本質(zhì)原理也是通過Service的方法拉起進(jìn)程囤捻,執(zhí)行相應(yīng)的doWork中的任務(wù)。

有一點(diǎn)需要注意雄妥,如果從后臺拉起進(jìn)程,因?yàn)檫@個時候App運(yùn)行在后臺依溯,能拿到的資源非常少老厌,很容易就會發(fā)生后臺ANR。

雖然Service的后臺ANR不會彈窗提示用戶黎炉,但是會影響任務(wù)的執(zhí)行成功率枝秤。所以,建議使用多進(jìn)程的方式慷嗜,讓任務(wù)運(yùn)行到子進(jìn)程中淀弹。

在多進(jìn)程的情況下丹壕,需要在RemoteWorkerService運(yùn)行的進(jìn)程中,修改Application中的onCreateattachBaseContext方法薇溃,定制屬于子進(jìn)程的初始化邏輯菌赖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市沐序,隨后出現(xiàn)的幾起案子琉用,更是在濱河造成了極大的恐慌,老刑警劉巖策幼,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邑时,死亡現(xiàn)場離奇詭異,居然都是意外死亡特姐,警方通過查閱死者的電腦和手機(jī)晶丘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唐含,“玉大人浅浮,你說我怎么就攤上這事【鹾” “怎么了脑题?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铜靶。 經(jīng)常有香客問我叔遂,道長,這世上最難降的妖魔是什么争剿? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任已艰,我火速辦了婚禮,結(jié)果婚禮上蚕苇,老公的妹妹穿的比我還像新娘哩掺。我一直安慰自己,他們只是感情好涩笤,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布嚼吞。 她就那樣靜靜地躺著,像睡著了一般蹬碧。 火紅的嫁衣襯著肌膚如雪舱禽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天恩沽,我揣著相機(jī)與錄音誊稚,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛里伯,可吹牛的內(nèi)容都是我干的城瞎。 我是一名探鬼主播,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼疾瓮,長吁一口氣:“原來是場噩夢啊……” “哼脖镀!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起爷贫,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤认然,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后漫萄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卷员,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年腾务,在試婚紗的時候發(fā)現(xiàn)自己被綠了毕骡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡岩瘦,死狀恐怖未巫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情启昧,我是刑警寧澤叙凡,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站密末,受9級特大地震影響握爷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜严里,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一新啼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸投剥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至戏锹,卻和暖如春冠胯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背景用。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工涵叮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伞插。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓割粮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親媚污。 傳聞我的和親對象是個殘疾皇子舀瓢,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評論 2 350

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