震驚!他竟然為了這個(gè)功能放棄了 5.0 以下的用戶碉哑!

JobScheduler 是一個(gè)新特性挚币,用于實(shí)現(xiàn)周期性或定時(shí)運(yùn)行的亮蒋,且對具體運(yùn)行時(shí)間點(diǎn)要求不高的后臺任務(wù),僅兼容 API level 21 以上妆毕。

JobScheduler 提供的功能其實(shí)在以往的系統(tǒng)上完全可以通過廣播加服務(wù)的方式實(shí)現(xiàn)慎玖,但它的可貴之處有二:

  • 節(jié)能 - 在于通過 JobScheduler 計(jì)劃的任務(wù)會經(jīng)過系統(tǒng)調(diào)度,以類似某些 ROM 中對齊喚醒的機(jī)制笛粘,把數(shù)個(gè)時(shí)間點(diǎn)相近的任務(wù)打包在一起執(zhí)行凄吏,創(chuàng)造休眠窗口,避免了系統(tǒng)被不斷喚醒闰蛔。

  • 易用 - 在于它 API 簡單易用,一聲明一計(jì)劃即可图柏。且原生提供了網(wǎng)絡(luò)狀況序六、是否充電、是否閑置等數(shù)個(gè)條件的限制蚤吹,節(jié)約了手動實(shí)現(xiàn)的工作例诀。

對于諸如每周清理緩存、手機(jī)閑置一分鐘后清理后臺應(yīng)用裁着、添加了新聯(lián)系人時(shí)同步到服務(wù)器之類定時(shí)或者周期運(yùn)行繁涂,而且早一點(diǎn)晚一點(diǎn)都不要緊的后臺工作,實(shí)現(xiàn)起來可是輕松極了二驰。

1. 實(shí)現(xiàn) JobService

第一步扔罪,決定任務(wù)被觸發(fā)時(shí)要做什么。
首先繼承 JobService 類桶雀,有兩個(gè)抽象方法必須實(shí)現(xiàn):

@Override
public boolean onStartJob(JobParameters params) {
    return false;
}

@Override
public boolean onStopJob(JobParameters params) {
    return false;
}

params 參數(shù)中保存著任務(wù) ID 和配置任務(wù)時(shí)攜帶的額外信息矿酵,用于區(qū)分不同的任務(wù)。

1.1. onStartJob()

任務(wù)啟動時(shí)被調(diào)用矗积,在這時(shí)執(zhí)行具體任務(wù)內(nèi)容全肮。方法返回值分兩種情況:

  • false - 表示任務(wù)在方法返回時(shí)就已經(jīng)同步地執(zhí)行完了
  • true - 表示方法返回時(shí)還有異步的任務(wù)沒有執(zhí)行完畢,執(zhí)行完時(shí)需要手動調(diào)用 jobFinished(JobParameters, boolean) 方法

jobFinished 方法的第二個(gè)參數(shù)指是否需要重新把這個(gè)任務(wù)加入計(jì)劃中棘捣,可以理解為任務(wù)執(zhí)行失敗了辜腺,值為 true 時(shí)會啟動任務(wù)重試,具體重試機(jī)制在下文詳述乍恐。

需要注意的是這個(gè)方法是在應(yīng)用的主線程執(zhí)行的评疗,因此平時(shí)開發(fā)時(shí)需要注意的問題在這里也適用。

1.2. onStopJob()

任務(wù)執(zhí)行完畢禁熏,被取消或者沒有滿足運(yùn)行條件而被放棄時(shí)調(diào)用壤巷,在這個(gè)方法內(nèi)做收尾善后工作。方法返回值同樣分為兩種情況:

  • false - 徹底放棄這個(gè)任務(wù)
  • true - 重新計(jì)劃這次任務(wù)瞧毙,啟動重試機(jī)制

不管返回值如何胧华,這個(gè)方法被調(diào)用的時(shí)候都應(yīng)該停止目前正在執(zhí)行的工作寄症。

1.3. 舉個(gè)例子

private boolean stillRunning;

@Override
public boolean onStartJob(final JobParameters params) {
    new Thread(() -> {
        PersistableBundle bundle = params.getExtras();
        int userId = bundle.getInt(KEY_PARAM_USER_ID);

        stillRunning = true;
        while (stillRunning) {
            sendSpam(userId);
        }
    }).start();
    return true;
}

@Override
public boolean onStopJob(JobParameters params) {
    stillRunning = false;
    return false;
}

JobService 寫完后在清單文件中注冊,聲明 android.permission.BIND_JOB_SERVICE 權(quán)限即可矩动。

<service
            android:name=".service.MyJobService"
            android:permission="android.permission.BIND_JOB_SERVICE"
            android:exported="true"/>

2. JobInfo.Builder

決定好了任務(wù)怎樣執(zhí)行有巧,接下來該決定任務(wù)何時(shí)執(zhí)行了。JobScheduler 使用 JobInfo 類來描述任務(wù)觸發(fā)的種種條件悲没, JobInfo 實(shí)例使用建造者模式來初始化篮迎。

2.1. 條件限制

需要注意的是以下條件都是嚴(yán)格限制的,如果條件一直沒有被滿足示姿,任務(wù)就一直不會執(zhí)行甜橱。如果希望即使條件沒有滿足也在某個(gè)時(shí)間點(diǎn)執(zhí)行任務(wù),則需要配合下文中的超時(shí)強(qiáng)制執(zhí)行功能使用栈戳。

  • setRequiredNetworkType(int)
    網(wǎng)絡(luò)類型限制岂傲,可選項(xiàng)有四個(gè):

    • NETWORK_TYPE_NONE:缺省值。對聯(lián)網(wǎng)狀態(tài)沒有要求子檀,離線也可以镊掖。
    • NETWORK_TYPE_ANY:只要聯(lián)網(wǎng)就可以。
    • NETWORK_TYPE_UNMETERED:要求非付費(fèi)網(wǎng)絡(luò)褂痰,『非付費(fèi)』的定義和系統(tǒng)里那個(gè)一樣難以捉摸亩进。
    • NETWORK_TYPE_NOT_ROAMING:要求非漫游網(wǎng)絡(luò)。
  • setRequiresCharging(boolean)
    要求正在充電缩歪,默認(rèn)關(guān)閉归薛。

  • setRequiresDeviceIdle(boolean)
    要求設(shè)備正在閑置狀態(tài),默認(rèn)關(guān)閉匪蝙。根據(jù)文檔說明苟翻,這里的『閑置狀態(tài)』是個(gè)寬泛的概念,指手機(jī)一段時(shí)間沒有被使用后進(jìn)入的狀態(tài)骗污。

2.2. 觸發(fā)條件

以下觸發(fā)條件只能粗略限制執(zhí)行時(shí)機(jī)崇猫,實(shí)際執(zhí)行的時(shí)間點(diǎn)還是要依靠系統(tǒng)調(diào)度的,并不能保證條件滿足了就會立刻執(zhí)行需忿。

  • addTriggerContentUri(TriggerContentUri)
    使用 ContentObserver 監(jiān)聽指定 URI诅炉,URI 內(nèi)容發(fā)生變動時(shí)觸發(fā)任務(wù)。設(shè)備重啟后失效屋厘。
    因?yàn)橐粋€(gè)任務(wù)只監(jiān)聽一次變動涕烧,如果想監(jiān)聽到所有變動,則需要在處理任務(wù)并返回方法之前重新計(jì)劃一個(gè)監(jiān)聽任務(wù)汗洒。

  • setTriggerContentUpdateDelay(long)
    在監(jiān)聽的 URI 發(fā)生變動之后延遲一段時(shí)間才執(zhí)行任務(wù)议纯。如果在延遲時(shí)間內(nèi)有新的變動發(fā)生了,就拋棄當(dāng)前等待的變動溢谤,對新的變動重新開始計(jì)時(shí)瞻凤,只針對最近的一次變動執(zhí)行計(jì)劃任務(wù)憨攒。

  • setTriggerContentMaxDelay(long)
    設(shè)置單次變動等待超時(shí)。在監(jiān)聽的 URI 發(fā)生變動后最多等待指定的時(shí)間阀参,如果系統(tǒng)一直沒有調(diào)度到這次變動的任務(wù)肝集,就在超時(shí)時(shí)強(qiáng)制執(zhí)行。

  • setPeriodic(long interval)
    循環(huán)執(zhí)行任務(wù)蛛壳。但是只保證在指定 interval 內(nèi)只執(zhí)行一次杏瞻,具體在這個(gè)時(shí)間段內(nèi)的哪個(gè)時(shí)間點(diǎn)執(zhí)行就不知道了。所以前一次任務(wù)到最后才執(zhí)行衙荐,而后一次任務(wù)一開始就執(zhí)行了捞挥,結(jié)果相當(dāng)于連續(xù)執(zhí)行了兩次任務(wù)也是有可能的。并不能當(dāng)定時(shí)器使用忧吟。
    間隔時(shí)間最短為十五分鐘树肃,也可以設(shè)置為更短,但執(zhí)行時(shí)會被強(qiáng)制限制到十五分鐘瀑罗。
    和 URI 監(jiān)聽功能一起使用沒有意義,同時(shí)設(shè)置的話會拋出異常雏掠。

  • setPeriodic(long interval, long flexMillis)
    同上斩祭,循環(huán)執(zhí)行任務(wù),區(qū)別在于可以把任務(wù)執(zhí)行的時(shí)間范圍限制在指定時(shí)間段內(nèi)的倒數(shù) flexMillis 毫秒里乡话。相比起上面的方法摧玫,可以做到更接近定時(shí)器的效果。
    flexMillis 也是有最短限制的绑青,第一不能小于五分鐘诬像,第二不能小于 interval 的 5%。所以 setPeriodic(30 * 60 * 1000, 0) 這種詭計(jì)用法就不要想了闸婴。

  • setMinimumLatency(long)
    設(shè)置最小延時(shí)坏挠,滿足條件后等待指定時(shí)間才執(zhí)行任務(wù)。
    由于循環(huán)任務(wù)本來就沒有具體的執(zhí)行時(shí)間點(diǎn)邪乍,設(shè)置延時(shí)也沒有意義降狠,所以不能和 setPeriodic 方法同時(shí)使用。

  • setOverrideDeadline(long)
    設(shè)置等待超時(shí)庇楞,超時(shí)后即使任何條件都沒滿足也會執(zhí)行任務(wù)榜配。同樣無法與 setPeriodic 方法同時(shí)使用。

2.3. 其他設(shè)置

  • setBackoffCriteria(long initialBackoffMillis, int backoffPolicy)
    設(shè)置任務(wù)執(zhí)行失敗時(shí)的重試策略吕晌。backoffPolicy 有兩種選項(xiàng)可用蛋褥,設(shè)置為 BACKOFF_POLICY_LINEAR 時(shí)每次重試的間隔相同,設(shè)置為 BACKOFF_POLICY_EXPONENTIAL 時(shí)每次重試的間隔都是上一次的兩倍睛驳。默認(rèn)情況下兩個(gè)值分別是 30 秒和 Exponential烙心。
    setRequiresDeviceIdle 同時(shí)使用的話膜廊,調(diào)用的時(shí)機(jī)會沖突,因此也是不能同時(shí)設(shè)置的弃理。

  • setExtras(PersistableBundle)
    Intent 中的 extras 類似溃论,用于攜帶額外信息。里面的內(nèi)容會被存儲在硬盤上痘昌,所以只允許攜帶基本類型钥勋。

  • setPersisted(boolean)
    在關(guān)機(jī)時(shí)把任務(wù)保存在硬盤上,重啟后可以繼續(xù)執(zhí)行計(jì)劃辆苔。默認(rèn)情況下重啟后服務(wù)是運(yùn)行不起來的算灸。
    但由于 Android 系統(tǒng)的限制,重啟后繼續(xù) URI 監(jiān)聽是做不到的驻啤,同時(shí)設(shè)置的話會拋異常菲驴。
    另外需要在配置文件里加上 RECEIVE_BOOT_COMPLETED 權(quán)限,不然也會拋異常骑冗。

2.4. 當(dāng)然赊瞬,

完全沒有限制是絕對不可以的,源碼里的注釋激烈地吐槽了這一點(diǎn):

// Allow jobs with no constraints - What am I, a database?

『你拿我當(dāng)什么了贼涩?』

3. 一切準(zhǔn)備停當(dāng)

最后使用 Context.getSystemService(Context.JOB_SCHEDULER_SERVICE) 拿到 JobScheduler 實(shí)例巧涧,調(diào)用它的 schedule(JobInfo) 方法,就可以安靜等待任務(wù)被執(zhí)行了遥倦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谤绳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子袒哥,更是在濱河造成了極大的恐慌缩筛,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件堡称,死亡現(xiàn)場離奇詭異瞎抛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)却紧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門婿失,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人啄寡,你說我怎么就攤上這事豪硅。” “怎么了挺物?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵懒浮,是天一觀的道長。 經(jīng)常有香客問我,道長砚著,這世上最難降的妖魔是什么次伶? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮稽穆,結(jié)果婚禮上冠王,老公的妹妹穿的比我還像新娘。我一直安慰自己舌镶,他們只是感情好柱彻,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著餐胀,像睡著了一般哟楷。 火紅的嫁衣襯著肌膚如雪体啰。 梳的紋絲不亂的頭發(fā)上茉贡,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機(jī)與錄音典尾,去河邊找鬼墨技。 笑死惩阶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的扣汪。 我是一名探鬼主播断楷,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼私痹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起统刮,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤紊遵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后侥蒙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暗膜,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年鞭衩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了学搜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡论衍,死狀恐怖瑞佩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坯台,我是刑警寧澤炬丸,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響稠炬,放射性物質(zhì)發(fā)生泄漏焕阿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一首启、第九天 我趴在偏房一處隱蔽的房頂上張望暮屡。 院中可真熱鬧,春花似錦毅桃、人聲如沸褒纲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽外厂。三九已至,卻和暖如春代承,著一層夾襖步出監(jiān)牢的瞬間汁蝶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工论悴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掖棉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓膀估,卻偏偏與公主長得像幔亥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子察纯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評論 2 361

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理帕棉,服務(wù)發(fā)現(xiàn),斷路器饼记,智...
    卡卡羅2017閱讀 134,716評論 18 139
  • Android Jobscheduler使用 Until android API 25 一香伴、Jobschedule...
    芥末末的沫閱讀 50,409評論 11 90
  • 國家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 11,010評論 6 13
  • 在茜茜家吃過早飯后,丁丁看了半小時(shí)熊出沒還要繼續(xù)看具则,我不干即纲,他鬧氣,紅著臉在桌子上尋摸可摔的東西博肋,找了一圈低斋,拿起美...
    張_小慢閱讀 348評論 0 3
  • 各路明星紛紛成為宇飛來分銷商 下圖是花和尚魯智深的扮演者與廣東省宇飛來管委會負(fù)責(zé)人甘總合影,同時(shí)也是我們宇飛來集團(tuán)...
    把你的腳步留下閱讀 235評論 0 0