在目前的Application開發(fā)中蚂斤,執(zhí)行一些異步任務(wù)非常普遍栓拜,其中有些任務(wù)的執(zhí)行周期甚至超過了Application的生命周期狼纬,比如一些下載數(shù)據(jù)的任務(wù)或者一些更新網(wǎng)絡(luò)資源的任務(wù)晋柱。有時(shí)我們需要執(zhí)行一些非立即開始的任務(wù)砸讳。Android提供了一些可以在applications中明智使用的API琢融,用于 執(zhí)行一些預(yù)期后臺任務(wù)。
選擇一個合適執(zhí)行方式可以提高application 的性能簿寂,同時(shí)可以節(jié)省設(shè)備的電量損耗吏奸。
Android M引入了 Doze mode用于在用戶不使用手機(jī)一段時(shí)間后最大可能地節(jié)省電量。
以下是幾個Android提供的API:
- Alarm Manager
- Job Scheduler
- GCM Network Manager
- Firebase Job Dispatcher
- Sync Adapter
使用Service的問題
Services允許在后臺長時(shí)間運(yùn)行任務(wù)陶耍。但是在后臺執(zhí)行Services相對來說比較耗電奋蔚。
Services即使不執(zhí)行什么有效的任務(wù),也會一直占用設(shè)備的資源烈钞。當(dāng)這些后臺Services監(jiān)聽系統(tǒng)的廣播時(shí)會加重以上的問題泊碑。
App運(yùn)行期的Schedule任務(wù)
在app運(yùn)行期執(zhí)行一些Schedule任務(wù)時(shí),推薦使用Handler配合Timer和Thread毯欣。這比使用Alarm Manager馒过, Job Scheduler等更簡單,也更高效酗钞。
App生命周期外的Schedule 任務(wù)
Alarm Manager
AlarmManager提供了系統(tǒng)級別alarm service的入口腹忽。它提供了在應(yīng)用運(yùn)行期外執(zhí)行操作的方法。AlarmManager可以在未來的某個時(shí)間啟動一個服務(wù)砚作,它可以在定時(shí)到達(dá)時(shí)觸發(fā)一個PendingIntent窘奏。
注冊后的alarm可以在設(shè)備鎖屏?xí)r依然是保留的(任務(wù)可以在設(shè)備鎖屏?xí)r觸發(fā)),但是在設(shè)備關(guān)閉或重啟之后就無效了葫录。
AlarmManager 可以在用于在特定時(shí)間觸發(fā)任務(wù)的操作着裹,并不提供其他更完善的執(zhí)行條件:如設(shè)備空閑、網(wǎng)絡(luò)可用或者開始充電等條件米同。
示例:當(dāng)我們需要在一個小時(shí)后或者每個小時(shí)執(zhí)行一些操作時(shí)骇扇,AlarmManager是一個不錯的選擇摔竿。但是無法在諸如網(wǎng)絡(luò)可用或者設(shè)備非充電狀態(tài)等狀態(tài)出現(xiàn)時(shí)觸發(fā)事件。
Job Scheduler
Job Scheduler 是所有提到的執(zhí)行預(yù)期任務(wù)首選的方式少孝,可以高效地執(zhí)行后臺任務(wù)继低。Job Scheduler API在Android 5.0(API 21)中引入的。
Job Scheduler運(yùn)行在設(shè)備有可用資源或者合適的條件時(shí)觸發(fā)任務(wù)稍走。在創(chuàng)建任務(wù)時(shí)可以自定義各種條件郁季。當(dāng)滿足生命的條件時(shí),系統(tǒng)將在app的 JobService中執(zhí)行定義的任務(wù)钱磅。Job Scheduler還可以根據(jù)Doze模式和應(yīng)用程序的待機(jī)限制執(zhí)行必要的操作梦裂。
用這種方式執(zhí)行任務(wù),可以讓設(shè)備長時(shí)間處于休眠狀態(tài)盖淡,從而延長電池使用時(shí)長年柠。一般來說Job Scheduler可以用來執(zhí)行對時(shí)間要求不嚴(yán)格的所有任務(wù)。
GCM Network Manager
GCM (Google Cloud Messaging)網(wǎng)絡(luò)管理擁有所有JobScheduler特性褪迟。GCM 網(wǎng)絡(luò)管理可以用于高效執(zhí)行所有重復(fù)或單次不緊急的任務(wù)冗恨,同時(shí)可以有效的節(jié)省設(shè)備電量。
它用于后向兼容味赃,可以在Android 5.0以下使用掀抹。在API 23及以上GCM實(shí)際使用了系統(tǒng)的JobSchedule。GCM 網(wǎng)絡(luò)管理使用了Google Play services中的scheduling 引擎心俗,因此只能在安裝了Google Play 的設(shè)備中使用傲武。
谷歌強(qiáng)烈建議GCM的用戶升級到FCM,使用Firebase Job Dispatcher執(zhí)行所有任務(wù)城榛。
Firebase Job Dispatcher
The Firebase JobDispatcher也是一個執(zhí)行后臺任務(wù)的庫揪利,它向后兼容(支持 API 21一下),可以在API 9+上運(yùn)行狠持。
The Firebase JobDispatcher可以運(yùn)行在未安裝Google Play 的設(shè)備上井仰。The Firebase JobDispatcher實(shí)際使用了AlarmManager嘴办,當(dāng)然如果設(shè)備安裝了Google Play,則The Firebase JobDispatcher使用Google Play中的Scheduling 引擎敛腌。
Sync Adapter
Sync Adapter設(shè)計(jì)用來同步本地和云端的數(shù)據(jù)泊藕。它只可以用來執(zhí)行這種任務(wù)搬男。在本地或者云端數(shù)據(jù)發(fā)生變化時(shí)可以觸發(fā)數(shù)據(jù)同步腺兴,或者定時(shí)觸發(fā)悼尾。Android系統(tǒng)會嘗試使用批量同步從而節(jié)省電量,未傳輸?shù)臄?shù)據(jù)將在隊(duì)列中等待同步昭齐。系統(tǒng)只會在聯(lián)網(wǎng)情況下嘗試進(jìn)行數(shù)據(jù)同步尿招。
當(dāng)然,還是建議盡可能使用JobScheduler, Firebase JobDispatcher, or GCM Network Manager等方法阱驾。
實(shí)踐
介紹了這么多就谜,我們來提供一個job scheduler的示例。
1. 創(chuàng)建 job service
繼承JobService來創(chuàng)建JobSchedulerService:
public class JobSchedulerService extends JobService {
@Override
public boolean onStartJob(JobParameters params) {
return false;
}
@Override
public boolean onStopJob(JobParameters params) {
return false;
}
}
JobService在main thread中執(zhí)行里覆,所有耗時(shí)邏輯應(yīng)在異步線程中丧荐。
同時(shí)還需要在AndroidManifest中注冊JobScheduler:
<application>
<service
android:name=”.JobSchedulerService “
android:permission=”android.permission.BIND_JOB_SERVICE”
android:exported=”true”/>
</application>
2. 創(chuàng)建一個JobInfo
創(chuàng)建JobInfo,如下所示需要傳遞 JobService喧枷。Job Builder允許創(chuàng)建job 執(zhí)行的多個條件虹统。
ComponentName serviceName = new ComponentName(context, JobSchedulerService.class);
JobInfo jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
.build();
3. 執(zhí)行任務(wù)
JobScheduler scheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
int result = scheduler.schedule(jobInfo);
if (result == JobScheduler.RESULT_SUCCESS) {
Log.d(TAG, “Job scheduled successfully!”);
}
可以在這里下載完整代碼:GitHub。
總結(jié)
在執(zhí)行預(yù)期任務(wù)隧甚,需要仔細(xì)考慮執(zhí)行任務(wù)的時(shí)機(jī)车荔,選擇合適的方式,考慮應(yīng)用的運(yùn)行性能和節(jié)電性能戚扳。
JobScheduler非常方便使用忧便,同時(shí)即使在系統(tǒng)重啟后依然可以執(zhí)行。但是要注意JobScheduler要求API 21+帽借。
歡迎閱讀珠增,原文地址:https://android.jlelse.eu/schedule-tasks-and-jobs-intelligently-in-android-e0b0d9201777
歡迎關(guān)注公眾號wutongke,定期推送移動開發(fā)前沿技術(shù)文章: