前言
項目實際場景中存在無網或弱網環(huán)境中操作記錄葛虐。應用程序是這樣工作的:
- 有網絡:執(zhí)行networkapi
- 弱網或無網絡:把需要提交的數(shù)據(jù)保存到room中钱豁,使用WorkManager將任務加入任務隊列,然后在網絡連接時發(fā)送請求
下圖為項目中提交記錄運用Room本地存儲和Workmanager進行任務隊列
Step1.弱網或無網絡本地數(shù)據(jù)存儲(Room)
1.網絡判斷
-
無網絡
mTopBar.addRightTextButton("提交", R.id.RIGHT).setOnClickListener { if (NetworkUtil.isNetworkAvailable(baseContext)) { goCommit() } else { insertLocalDB() } }
-
弱網(網絡超時,且當客戶端發(fā)生弱網)
ApiServerResponse .getInstence() .createEffectRecord(map, object : RetrofitObserver<BaseResponse<Any>>(this) { override fun onSuccess(response: BaseResponse<Any>) { dismiss() showToast("創(chuàng)建成功") finish() } override fun onNetError(e: Throwable) { dismiss() insertLocalDB() ExceptionHandle.handleException(e) } })
2.插入數(shù)據(jù)疯淫,開啟后臺任務
/**
* 無網絡提交本地數(shù)據(jù)庫
* */
private fun insertLocalDB() {
val record = Record('','','',...)
//插入數(shù)據(jù)
PmpDataBase.getInstance(baseContext).planDao().insertRecord(record)
//判斷是否已開啟后臺服務
val hasLocalRecord: Boolean = MMKVUtil.decodeBoolean(Constants.SP_KEY_LOCAL_RECORD)!!
LogUtils.d("RecordLocalRecord", hasLocalRecord)
if (!hasLocalRecord) {
//沒開啟就去開啟
MMKVUtil.encode(Constants.SP_KEY_LOCAL_RECORD, true)
val request = OneTimeWorkRequest.Builder(RecordWorker::class.java)
.setConstraints(getConstraints())
.build()
//隊列
WorkManager.getInstance(this@CycleEffectActivity).enqueue(request)
WorkManager.getInstance(this@CycleEffectActivity)
.getWorkInfoByIdLiveData(request.id)
.observe(this@CycleEffectActivity, {//通過id
if (it != null && it.state.isFinished) {
LogUtils.d("RecordDoWorkResult", "success")
MMKVUtil.encode(Constants.SP_KEY_LOCAL_RECORD, false)
WorkManager.getInstance(this@CycleEffectActivity)
.cancelWorkById(request.id)
}
})
}
}
/**
* Constraints
**/
private fun getConstaints():Constraints{
return Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) // 網絡狀態(tài)
.setRequiresBatteryNotLow(true) // 不在電量不足時執(zhí)行
.setRequiresCharging(true) // 在充電時執(zhí)行
.setRequiresStorageNotLow(true) // 不在存儲容量不足時執(zhí)行
.setRequiresDeviceIdle(true) // 在待機狀態(tài)下執(zhí)行地来,須要 API 23
.build()
}
Step2.后臺任務調度(WorkManager)
無論應用程序進程是否存在,WorkManager都會處理在滿足各種約束條件時需要運行的后臺工作熙掺。
后臺工作可以在應用程序位于后臺、前臺或者應用在前臺打開即將轉到后臺的時候啟動。
無論應用程序在做什么烦粒,后臺工作都應該繼續(xù)進行瘸羡,或者在 Android 終止其進程時重啟其后臺工作。
WorkManager設計用于在滿足某些條件時執(zhí)行操作(e.g.:有網絡狀態(tài)時缆镣,不在電量不足時執(zhí)行芽突,在充電時執(zhí)行等)
/**
* @作者 : JayGengi
* @時間 : 2022/3/17 9:38
* @描述 : 記錄【record】后臺任務:本地room db文件 記錄內容提交服務器
*/
class RecordWorker(var context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
override fun doWork(): Result {
//接收傳遞過來的數(shù)據(jù)
LogUtils.d("RecordDoWork1")
return try {
val localRecordList = PmpDataBase.getInstance(context)
.planDao().localRecordList as ArrayList<Record>
LogUtils.d("RecordDoWorkListSize", localRecordList.size.toString() + "")
if (null != localRecordList && localRecordList.size > 0) {
//執(zhí)行
submitLocalDBRecord(localRecordList)
}
Result.success()
} catch (exception: Exception) {
LogUtils.d("RecordDoWorkFailure")
exception.printStackTrace()
Result.failure()
}
}