WorkManager調(diào)研分析


  • 背景:通常我們在開發(fā)過程中處理后臺任務(wù)的時候可能是自己維系一個線程池或者通過一個后臺任務(wù)來完成我們的工作枪孩,然后對于某些特定的需求還需要自己進行網(wǎng)絡(luò)條件奏属,電量等信息的攔截判斷處理福压。這個實現(xiàn)過程比較繁瑣仿村,而且每個類似的需求都寫一套相同的邏輯就顯得很累贅了锐朴。通過谷歌新推出的WorkManager SDK能很好的解決上述問題
  • 原理:根據(jù)當前系統(tǒng)的API版本和當前應(yīng)用的存活狀態(tài)來選擇對應(yīng)的方式來執(zhí)行任務(wù),當應(yīng)用在運行的時候蔼囊,會在應(yīng)用進程中開啟一個子線程來執(zhí)行任務(wù)包颁,如果應(yīng)用被殺掉了,WorkManager會根據(jù)當前系統(tǒng)API版本來選擇是使用JobScheduler(API21)還是AlarmManager(API14-API20)來執(zhí)行任務(wù)(具體的執(zhí)行時機在某些國產(chǎn)系統(tǒng)上可能會發(fā)生變化)压真。
  • 結(jié)論:對于可延時的執(zhí)行的后臺任務(wù)建議遷移到WorkManager上娩嚼,節(jié)約APP的電量消耗(如日志上報等),而對于需要立刻執(zhí)行的任務(wù)建議還是使用ThreadPool或者前臺服務(wù)等

一滴肿、基本功能


  • 1.1 運作流程

    • 通過WorkManager將Woker任務(wù)添加到任務(wù)隊列中岳悟,在添加的過程中可以指定約束條件(充電狀態(tài)、WIFI狀態(tài)泼差、手機存儲空間等等)贵少。只有當約束條件滿足時才會執(zhí)行我們的Worker。
  • 1.2 Worker

    • 表示一個要執(zhí)行的任務(wù)堆缘,我們需要繼承并顯示該類滔灶,并在doWork方法中實現(xiàn)我們自己的任務(wù)邏輯,通過不同的返回值表示當前Work的執(zhí)行情況
      • Worker.Result.SUCCES 表示任務(wù)執(zhí)行成功吼肥,如果有下一個任務(wù)會接著執(zhí)行下一個任務(wù)
      • Worker.Result.FAILURE 表示任務(wù)執(zhí)行失敗录平,整個任務(wù)鏈就此中斷
      • Worker.Result.RETRY 通過WorkManager根據(jù)重試策略嘗試執(zhí)行該任務(wù)
  • 1.3 WorkRequest

    • Worker的包裝類麻车,最后添加到WorkManager中的就是當前WorkRequest對象,通過WorkRequest對象可以給我們的Worker附加額外的功能
      • 執(zhí)行任務(wù)時的約束條件(電量斗这、網(wǎng)絡(luò)等)
      • 當Worker執(zhí)行失敗時的重試策略
      • 設(shè)置當前Worker的入?yún)ⅲ▓?zhí)行任務(wù)時可攜帶額外的參數(shù)給Worker使用)
      • 設(shè)置當前Worker接受的入?yún)⒑喜⒉呗裕▋H當上一個任務(wù)存在多個并行的Worker且返回相同的KEY時有作用动猬,在下面的入?yún)⒑统鰠⒛K會詳細介紹)
    • 兩個子類
      • OneTimeWorkRequest
      • PeriodicWorkRequest(下方模塊有介紹)
  • 1.4 WorkManager
    * 主要用來管理任務(wù)請求和任務(wù)隊列,將Worker的包裝者WorkRequest對象入隊表箭,同時還可以指定多個任務(wù)執(zhí)行的先后順序赁咙,實現(xiàn)串行或者并行的任務(wù)鏈。

  • 1.5 Constraints(添加約束條件)

    • setRequiredNetworkType(設(shè)置網(wǎng)絡(luò)相關(guān)的約束條件)
      • NetworkType.NOT_REQUIRED【對網(wǎng)絡(luò)沒有要求】
      • NetworkType.CONNECTED【網(wǎng)絡(luò)連接】
      • NetworkType.UNMETERED【不計費的網(wǎng)絡(luò)比如WIFI下執(zhí)行】
      • NetworkType.NOT_ROAMING【非漫游網(wǎng)絡(luò)狀態(tài)】
      • NetworkType.METERED 【計費網(wǎng)絡(luò)比如3G免钻,4G下執(zhí)行彼水。】
    • setRequiresDeviceIdle (設(shè)置設(shè)備是否空閑)
    • setRequiresCharging(設(shè)置設(shè)備是否處于充電狀態(tài))
    • setRequiresBatteryNotLow(設(shè)備電量是否不應(yīng)低于臨界閥值)
    • setRequiresStorageNotLow(設(shè)備存儲空間低于臨界閥值)
    • addTriggerContentUri【API24】(對某個ContentUri的內(nèi)容變化進行監(jiān)聽)
      • 通過內(nèi)容提供者修改聯(lián)系人极舔,當聯(lián)系人修改時猿涨,觸發(fā)這個監(jiān)聽回調(diào)
        注:因為內(nèi)容提供者的修改可能會短時間內(nèi)多次調(diào)用,為了不影響監(jiān)聽線程姆怪,這里需要另起新的線程或者來執(zhí)行

二叛赚、高級功能


  • 2.1 任務(wù)類型
    • OneTimeWorkRequest 【只執(zhí)行一次的任務(wù)】
      •   OneTimeWorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWorker.class).build();
        
    • PeriodicWorkRequest 【一定周期間隔內(nèi)重復(fù)執(zhí)行的任務(wù)】
      • 周期性任務(wù),官方設(shè)定最短執(zhí)行周期為15分鐘稽揭,同時因為系統(tǒng)的優(yōu)化策略俺附,后面周期性的任務(wù)執(zhí)行可能會有一定的時間延遲,無法做到精準時間執(zhí)行溪掀。
    •    PeriodicWorkRequest build = new PeriodicWorkRequest.Builder(MyWorker.class, 25, TimeUnit.MILLISECONDS).build();
      
  • 2.2 任務(wù)鏈
    • 串行鏈
      •   WorkManager.getInstance().beginWith(workRequestA)
              .then(workRequestB)
              .then(workRequestC)
              .enqueue()
        
      • 依次執(zhí)行workRequestA 事镣,workRequestB,workRequestC揪胃。每個階段完成之后通過在doWork方法中返回Worker.Result.SUCCES來進入下一個workRequest璃哟。如果其中任何一個workRequest返回Worker.Result.FAILURE,那么后續(xù)的workRequest都不會執(zhí)行了喊递,就此中斷
    • 并發(fā)鏈
      •  WorkManager.getInstance()
             .beginWith(workA1, workA2, workA3)
             .then(workB1, workB2)
             .then(workC1, workC2)
             .enqueue();
        
      • 首先并行執(zhí)行workA1, workA2, workA3任務(wù)随闪,等待這三個任務(wù)都執(zhí)行完之后再并發(fā)執(zhí)行workB1, workB2任務(wù),等待著兩個任務(wù)執(zhí)行完畢之后再繼續(xù)并發(fā)執(zhí)行workC1, workC2任務(wù)骚勘。
    • 組合鏈
      •     //A,B任務(wù)鏈
            WorkContinuation continuationAB = WorkManager.getInstance().beginWith(requestA).then(requestB);
            //C,D任務(wù)鏈
            WorkContinuation continuationCD = WorkManager.getInstance().beginWith(requestC).then(requestD);
            // 對AB和CD進行組合
            WorkContinuation.combine(continuationAB, continuationCD).then(requestE).enqueue();
        
      • A/B串行執(zhí)行铐伴,C/D串行執(zhí)行,最后讓A/B和C/D這兩個組合任務(wù)并發(fā)執(zhí)行俏讹。
  • 2.3 任務(wù)標簽
    • 作用:對WorkerRequest進行標簽分組当宴,同時還可以操作同一分組標簽,比如取消該標簽下的所有任務(wù)泽疆,或者獲取該標簽下的所有任務(wù)户矢,然后查詢各個任務(wù)現(xiàn)在的執(zhí)行狀態(tài)
    •  OneTimeWorkRequest cacheCleanupTask =new OneTimeWorkRequest.Builder(WorkerA.class)
            .addTag("groupA")
            .build();
      
  • 2.4 任務(wù)參數(shù)傳遞
    • 作用:當我們在執(zhí)行單個任務(wù)或者一個任務(wù)鏈的時候,我們可能需要將參數(shù)帶入到第一個任務(wù)中殉疼,或者需要將第一個任務(wù)執(zhí)行后的返回結(jié)果帶入到第二個任務(wù)中梯浪。
    • 初始化任務(wù)時傳遞參數(shù):
      •     Data workData = new Data.Builder() // Data大小需要控制在10k內(nèi)
                     .putInt("NAME", "Android Develop") // 參數(shù)可以為任意類型
                     .putInt("AGE", 101)
                     .build();
            OneTimeWorkRequest workRequestA = new OneTimeWorkRequest.Builder(WorkerA.class)
                     .setInputData(workData)
                     .build();
            WorkManager.getInstance().enqueue(mathWork);
        
    • 將當前任務(wù)的執(zhí)行結(jié)果傳遞給下一個任務(wù)
      •     public class MathWorker extends Worker {
               @Override
               public Worker.WorkerResult doWork() {
                   String sourceName = getInputData().getString("NAME", "");
                   int sourceAge = getInputData().getInt("AGE", 0);
                   int formatAge = sourceAge + 101;
                   Data output = new Data.Builder()
                        .putInt("AGE", formatAge)
                        .build();
                   setOutputData(output);
                   return WorkerResult.SUCCESS;
           }}
        
    • 多個相同參數(shù)來源的合并
      • 參數(shù)合并:當需要將多個任務(wù)的輸出作為一個任務(wù)的輸入時就會涉及到一個參數(shù)合并的問題捌年,如果多個任務(wù)的輸出中由好幾個key都是一樣的,那么需要由開發(fā)者自己來決定應(yīng)該使用什么樣的參數(shù)合并規(guī)則
      • 合并規(guī)則之ArrayCreatingInputMerger
        •  OneTimeWorkRequest workerRequestA = new OneTimeWorkRequest.Builder(WorkerA.class).setInputMerger(ArrayCreatingInputMerger.class).build();
          
        • 對于該合并規(guī)則來說驱证,同一個的Key對應(yīng)的Value都會放在一個數(shù)組中延窜,數(shù)據(jù)會隨著入?yún)⒌脑龆喽兇罅低螅瑢τ谙掠稳蝿?wù)想要獲取數(shù)據(jù)的方法為getXXXArray()抹锄,如getIntArray();
      • 合并規(guī)則之OverwritingInputMerger
        • OneTimeWorkRequest workerRequestB = new OneTimeWorkRequest.Builder(WorkerA.class).setInputMerger(OverwritingInputMerger.class).build();
          
        • 顧名思義,后到的key-value會覆蓋已存在的key-value
      • 自定義合并規(guī)則
        • 需要自定義類荠藤,然后繼承抽象類InputMerger伙单,覆寫merge方法,實現(xiàn)自己的merge邏輯

三哈肖、存在的限制

  • 周期任務(wù)最小時間間隔為15分鐘
  • 任務(wù)隊列最大限制為100個
  • 參數(shù)傳遞最大數(shù)據(jù)量為10kb
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吻育,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子淤井,更是在濱河造成了極大的恐慌布疼,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件币狠,死亡現(xiàn)場離奇詭異游两,居然都是意外死亡,警方通過查閱死者的電腦和手機漩绵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門贱案,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人止吐,你說我怎么就攤上這事宝踪。” “怎么了碍扔?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵瘩燥,是天一觀的道長。 經(jīng)常有香客問我不同,道長颤芬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任套鹅,我火速辦了婚禮站蝠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘卓鹿。我一直安慰自己菱魔,他們只是感情好,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布吟孙。 她就那樣靜靜地躺著澜倦,像睡著了一般聚蝶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上藻治,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天碘勉,我揣著相機與錄音,去河邊找鬼桩卵。 笑死验靡,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的雏节。 我是一名探鬼主播胜嗓,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼钩乍!你這毒婦竟也來了辞州?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤寥粹,失蹤者是張志新(化名)和其女友劉穎变过,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涝涤,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡媚狰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了妄痪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哈雏。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衫生,靈堂內(nèi)的尸體忽然破棺而出裳瘪,到底是詐尸還是另有隱情,我是刑警寧澤罪针,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布彭羹,位于F島的核電站,受9級特大地震影響泪酱,放射性物質(zhì)發(fā)生泄漏派殷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一墓阀、第九天 我趴在偏房一處隱蔽的房頂上張望毡惜。 院中可真熱鬧,春花似錦斯撮、人聲如沸经伙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽帕膜。三九已至枣氧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間垮刹,已是汗流浹背达吞。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓维费,卻偏偏與公主長得像,于是被迫代替她去往敵國和親契耿。 傳聞我的和親對象是個殘疾皇子瞒大,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

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