Android5.0中JobScheduler的使用方法
在Android 5.0中使用JobScheduler
•原文鏈接 : using-the-jobscheduler-api-on-android-lollipop
•譯者 : Mr.Simple
•校對(duì)者 : Mr.Simple
在這篇文章中,你會(huì)學(xué)習(xí)到在Android 5.0中如何使用JobScheduler API。JobScheduler API允許開發(fā)者在符合某些條件時(shí)創(chuàng)建執(zhí)行在后臺(tái)的任務(wù)。
介紹
在android開發(fā)中,會(huì)存在這么些場(chǎng)景 : 你需要在稍后的某個(gè)時(shí)間點(diǎn)或者當(dāng)滿足某個(gè)特定的條件時(shí)執(zhí)行一個(gè)任務(wù),例如當(dāng)設(shè)備接通電源適配器或者連接到WIFI。幸運(yùn)的是在API 21 ( Android 5.0,即Lollipop )中,google提供了一個(gè)新叫做JobScheduler API的組件來處理這樣的場(chǎng)景。
當(dāng)一系列預(yù)置的條件被滿足時(shí),JobScheduler API為你的應(yīng)用執(zhí)行一個(gè)操作。與AlarmManager不同的是這個(gè)執(zhí)行時(shí)間是不確定的。除此之外,JobScheduler API允許同時(shí)執(zhí)行多個(gè)任務(wù)。這允許你的應(yīng)用執(zhí)行某些指定的任務(wù)時(shí)不需要考慮時(shí)機(jī)控制引起的電池消耗。
這篇文章中,你會(huì)學(xué)到關(guān)于JobScheduler API更多的東西以及在你的應(yīng)用中用于運(yùn)行一個(gè)簡(jiǎn)單的后臺(tái)任務(wù)的JobService,這篇文章中所展示的代碼你都可以在github中找到。
1. 創(chuàng)建Job Service
首先,你需要?jiǎng)?chuàng)建一個(gè)API最低為21的Android項(xiàng)目,因此JobScheduler是最近的版本才加入Android的,在寫這篇文章的時(shí)候,它還沒有兼容庫(kù)支持。
假定你使用的是Android Studio,當(dāng)你點(diǎn)擊了創(chuàng)建項(xiàng)目的完成按鈕之后,你會(huì)得到一個(gè)”hello world”的應(yīng)用骨架。你要做的第一步就是創(chuàng)建一個(gè)新的Java類。為了簡(jiǎn)單起見,讓我們創(chuàng)建一個(gè)繼承自JobService且名字為JobSchedulerService的類,這個(gè)類必須實(shí)現(xiàn)兩個(gè)方法,分別是onStartJob(JobParameters params)和 onStopJob(JobParameters params);
public class JobSchedulerService extends JobService { @Override public boolean onStartJob(JobParameters params) { return false; } @Override public boolean onStopJob(JobParameters params) { return false; } }
當(dāng)任務(wù)開始時(shí)會(huì)執(zhí)行onStartJob(JobParameters params)方法,因?yàn)檫@是系統(tǒng)用來觸發(fā)已經(jīng)被執(zhí)行的任務(wù)。正如你所看到的,這個(gè)方法返回一個(gè)boolean值。如果返回值是false,系統(tǒng)假設(shè)這個(gè)方法返回時(shí)任務(wù)已經(jīng)執(zhí)行完畢。如果返回值是true,那么系統(tǒng)假定這個(gè)任務(wù)正要被執(zhí)行,執(zhí)行任務(wù)的重?fù)?dān)就落在了你的肩上。當(dāng)任務(wù)執(zhí)行完畢時(shí)你需要調(diào)用jobFinished(JobParameters params, boolean needsRescheduled)來通知系統(tǒng)。
當(dāng)系統(tǒng)接收到一個(gè)取消請(qǐng)求時(shí),系統(tǒng)會(huì)調(diào)用onStopJob(JobParameters params)方法取消正在等待執(zhí)行的任務(wù)。很重要的一點(diǎn)是如果onStartJob(JobParameters params)返回false,那么系統(tǒng)假定在接收到一個(gè)取消請(qǐng)求時(shí)已經(jīng)沒有正在運(yùn)行的任務(wù)。換句話說,onStopJob(JobParameters params)在這種情況下不會(huì)被調(diào)用。
需要注意的是這個(gè)job service運(yùn)行在你的主線程,這意味著你需要使用子線程,handler, 或者一個(gè)異步任務(wù)來運(yùn)行耗時(shí)的操作以防止阻塞主線程。因?yàn)槎嗑€程技術(shù)已經(jīng)超出了我們這篇文章的范圍,讓我們簡(jiǎn)單實(shí)現(xiàn)一個(gè)Handlder來執(zhí)行我們?cè)贘obSchedulerService定義的任務(wù)吧。
private Handler mJobHandler = new Handler( new Handler.Callback() { @Override public boolean handleMessage( Message msg ) { Toast.makeText( getApplicationContext(), "JobService task running", Toast.LENGTH_SHORT ) .show(); jobFinished( (JobParameters) msg.obj, false ); return true; } } );
在Handler中,你需要實(shí)現(xiàn)handleMessage(Message msg)方法來處理你的任務(wù)邏輯。在這個(gè)例子中,我們盡量保證例子簡(jiǎn)單,因此我們只在handleMessage(Message msg)中顯示了一個(gè)Toast,這里就是你要寫你的任務(wù)邏輯( 耗時(shí)操作 )的地方,比如同步數(shù)據(jù)等。
當(dāng)任務(wù)執(zhí)行完畢之后,你需要調(diào)用jobFinished(JobParameters params, boolean needsRescheduled)來讓系統(tǒng)知道這個(gè)任務(wù)已經(jīng)結(jié)束,系統(tǒng)可以將下一個(gè)任務(wù)添加到隊(duì)列中。如果你沒有調(diào)用jobFinished(JobParameters params, boolean needsRescheduled),你的任務(wù)只會(huì)執(zhí)行一次,而應(yīng)用中的其他任務(wù)就不會(huì)被執(zhí)行。
jobFinished(JobParameters params, boolean needsRescheduled)的兩個(gè)參數(shù)中的params參數(shù)是從JobService的onStartJob(JobParameters params)的params傳遞過來的,needsRescheduled參數(shù)是讓系統(tǒng)知道這個(gè)任務(wù)是否應(yīng)該在最處的條件下被重復(fù)執(zhí)行。這個(gè)boolean值很有用,因?yàn)樗该髁四闳绾翁幚碛捎谄渌驅(qū)е氯蝿?wù)執(zhí)行失敗的情況,例如一個(gè)失敗的網(wǎng)絡(luò)請(qǐng)求調(diào)用。
創(chuàng)建了Handler實(shí)例之后,你就可以實(shí)現(xiàn)onStartJob(JobParameters params) 和onStopJob(JobParameters params)方法來控制你的任務(wù)了。你可能已經(jīng)注意到在下面的代碼片段中onStartJob(JobParameters params)返回了true。這是因?yàn)槟阋ㄟ^Handler實(shí)例來控制你的操作,
這意味著Handler的handleMessage方法的執(zhí)行時(shí)間可能比onStartJob(JobParameters params)更長(zhǎng)。返回true,你會(huì)讓系統(tǒng)知道你會(huì)手動(dòng)地調(diào)用jobFinished(JobParameters params, boolean needsRescheduled)方法。
@Override public boolean onStartJob(JobParameters params) { mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) ); return true; } @Override public boolean onStopJob(JobParameters params) { mJobHandler.removeMessages( 1 ); return false; }
一旦你在Java部分做了上述工作之后,你需要到AndroidManifest.xml中添加一個(gè)service節(jié)點(diǎn)讓你的應(yīng)用擁有綁定和使用這個(gè)JobService的權(quán)限。
<service android:name=".JobSchedulerService" android:permission="android.permission.BIND_JOB_SERVICE" />
2. 創(chuàng)建一個(gè)JobScheduler對(duì)象
隨著JobSchedulerService構(gòu)建完畢,我們可以開始研究你的應(yīng)用如何與JobScheduler API進(jìn)行交互了。第一件要做的事就是你需要?jiǎng)?chuàng)建一個(gè)JobScheduler對(duì)象,在實(shí)例代碼的MainActivity中我們通過getSystemService( Context.JOB_SCHEDULER_SERVICE )初始化了一個(gè)叫做mJobScheduler的JobScheduler對(duì)象。
mJobScheduler = (JobScheduler) getSystemService( Context.JOB_SCHEDULER_SERVICE );
當(dāng)你想創(chuàng)建定時(shí)任務(wù)時(shí),你可以使用JobInfo.Builder來構(gòu)建一個(gè)JobInfo對(duì)象,然后傳遞給你的Service。JobInfo.Builder接收兩個(gè)參數(shù),第一個(gè)參數(shù)是你要運(yùn)行的任務(wù)的標(biāo)識(shí)符,第二個(gè)是這個(gè)Service組件的類名。
JobInfo.Builder builder = new JobInfo.Builder( 1, new ComponentName( getPackageName(), JobSchedulerService.class.getName() ) );
這個(gè)builder允許你設(shè)置很多不同的選項(xiàng)來控制任務(wù)的執(zhí)行。下面的代碼片段就是展示了如何設(shè)置以使得你的任務(wù)可以每隔三秒運(yùn)行一次。
builder.setPeriodic( 3000 );
其他設(shè)置方法 :
•setMinimumLatency(long minLatencyMillis):
這個(gè)函數(shù)能讓你設(shè)置任務(wù)的延遲執(zhí)行時(shí)間(單位是毫秒),這個(gè)函數(shù)與setPeriodic(long time)方法不兼容,如果這兩個(gè)方法同時(shí)調(diào)用了就會(huì)引起異常;
•setOverrideDeadline(long maxExecutionDelayMillis):
這個(gè)方法讓你可以設(shè)置任務(wù)最晚的延遲時(shí)間。如果到了規(guī)定的時(shí)間時(shí)其他條件還未滿足,你的任務(wù)也會(huì)被啟動(dòng)。與setMinimumLatency(long time)一樣,這個(gè)方法也會(huì)與setPeriodic(long time),同時(shí)調(diào)用這兩個(gè)方法會(huì)引發(fā)異常。
•setPersisted(boolean isPersisted):
這個(gè)方法告訴系統(tǒng)當(dāng)你的設(shè)備重啟之后你的任務(wù)是否還要繼續(xù)執(zhí)行。
•setRequiredNetworkType(int networkType):
這個(gè)方法讓你這個(gè)任務(wù)只有在滿足指定的網(wǎng)絡(luò)條件時(shí)才會(huì)被執(zhí)行。默認(rèn)條件是JobInfo.NETWORK_TYPE_NONE,這意味著不管是否有網(wǎng)絡(luò)這個(gè)任務(wù)都會(huì)被執(zhí)行。另外兩個(gè)可選類型,一種是JobInfo.NETWORK_TYPE_ANY,它表明需要任意一種網(wǎng)絡(luò)才使得任務(wù)可以執(zhí)行。另一種是JobInfo.NETWORK_TYPE_UNMETERED,它表示設(shè)備不是蜂窩網(wǎng)絡(luò)( 比如在WIFI連接時(shí) )時(shí)任務(wù)才會(huì)被執(zhí)行。
•setRequiresCharging(boolean requiresCharging):
這個(gè)方法告訴你的應(yīng)用,只有當(dāng)設(shè)備在充電時(shí)這個(gè)任務(wù)才會(huì)被執(zhí)行。
•setRequiresDeviceIdle(boolean requiresDeviceIdle):
這個(gè)方法告訴你的任務(wù)只有當(dāng)用戶沒有在使用該設(shè)備且有一段時(shí)間沒有使用時(shí)才會(huì)啟動(dòng)該任務(wù)。
需要注意的是setRequiredNetworkType(int networkType), setRequiresCharging(boolean requireCharging) and setRequiresDeviceIdle(boolean requireIdle)者幾個(gè)方法可能會(huì)使得你的任務(wù)無法執(zhí)行,除非調(diào)用setOverrideDeadline(long time)設(shè)置了最大延遲時(shí)間,使得你的任務(wù)在為滿足條件的情況下也會(huì)被執(zhí)行。一旦你預(yù)置的條件被設(shè)置,你就可以構(gòu)建一個(gè)JobInfo對(duì)象,然后通過如下所示的代碼將它發(fā)送到你的JobScheduler中。
if( mJobScheduler.schedule( builder.build() ) <= 0 ) { //If something goes wrong }
你可能注意到了,這個(gè)schedule方法會(huì)返回一個(gè)整型。如果schedule方法失敗了,它會(huì)返回一個(gè)小于0的錯(cuò)誤碼。否則它會(huì)我們?cè)贘obInfo.Builder中定義的標(biāo)識(shí)id。
如果你的應(yīng)用想停止某個(gè)任務(wù),你可以調(diào)用JobScheduler對(duì)象的cancel(int jobId)來實(shí)現(xiàn);如果你想取消所有的任務(wù),你可以調(diào)用JobScheduler對(duì)象的cancelAll()來實(shí)現(xiàn)。
mJobScheduler.cancelAll();
到了這里,你現(xiàn)在應(yīng)該已經(jīng)知道如何在你的應(yīng)用中使用JobScheduler API來執(zhí)行批量任務(wù)和后臺(tái)操作了。
結(jié)論
這篇文章中,你學(xué)會(huì)了怎么實(shí)現(xiàn)一個(gè)使用Handler對(duì)象來運(yùn)行后臺(tái)任務(wù)的JobService子類,你也學(xué)會(huì)了如何使用JobInfo.Builder來設(shè)置JobService。掌握了這些之后,你可以在減少資源消耗的同時(shí)提升應(yīng)用的效率。
更多文章
更多優(yōu)秀文章請(qǐng)猛擊android-tech-frontier。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android側(cè)滑導(dǎo)航欄的實(shí)例代碼
這篇文章主要介紹了Android側(cè)滑導(dǎo)航欄的實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-01-01Android中使用TextView實(shí)現(xiàn)文字跑馬燈效果
本文主要介紹了Android中使用TextView實(shí)現(xiàn)文字走馬燈效果的方法解析。具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-04-04Android系統(tǒng)檢測(cè)程序內(nèi)存占用各種方法
這篇文章主要介紹了Android系統(tǒng)檢測(cè)程序內(nèi)存占用各種方法,本文講解了檢查系統(tǒng)總內(nèi)存、檢查某個(gè)程序的各類型內(nèi)存占用、檢查程序狀態(tài)、檢查程序各部分的內(nèi)存占用等內(nèi)容,需要的朋友可以參考下2015-03-03一分鐘實(shí)現(xiàn)Android遮罩引導(dǎo)視圖
本文通過一分鐘的時(shí)間教大家實(shí)現(xiàn)Android遮罩引導(dǎo)視圖,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03android使用PullToRefresh框架實(shí)現(xiàn)ListView下拉刷新上拉加載更多
這篇文章主要介紹了android使用PullToRefresh框架實(shí)現(xiàn)ListView下拉刷新上拉加載更多,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12android: targetSdkVersion升級(jí)中Only fullscreen activities can r
這篇文章主要給大家介紹了關(guān)于Android target SDK和build tool版本升級(jí)中遇到Only fullscreen activities can request orientation問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-09-09Android如何實(shí)現(xiàn)接收和發(fā)送短信
這篇文章主要為大家詳細(xì)介紹了Android如何實(shí)現(xiàn)接收和發(fā)送短信,具有一定的實(shí)用性,感興趣的小伙伴們可以參考一下2016-08-08