前言
項(xiàng)目實(shí)際場(chǎng)景中存在無(wú)網(wǎng)或弱網(wǎng)環(huán)境中操作記錄。應(yīng)用程序是這樣工作的:
- 有網(wǎng)絡(luò):執(zhí)行networkapi
- 弱網(wǎng)或無(wú)網(wǎng)絡(luò):把需要提交的數(shù)據(jù)保存到room中,使用WorkManager將任務(wù)加入任務(wù)隊(duì)列,然后在網(wǎng)絡(luò)連接時(shí)發(fā)送請(qǐng)求
下圖為項(xiàng)目中提交記錄運(yùn)用Room本地存儲(chǔ)和Workmanager進(jìn)行任務(wù)隊(duì)列

Step1.弱網(wǎng)或無(wú)網(wǎng)絡(luò)本地?cái)?shù)據(jù)存儲(chǔ)(Room)
1.網(wǎng)絡(luò)判斷
-
無(wú)網(wǎng)絡(luò)
mTopBar.addRightTextButton("提交", R.id.RIGHT).setOnClickListener { if (NetworkUtil.isNetworkAvailable(baseContext)) { goCommit() } else { insertLocalDB() } } -
弱網(wǎng)(網(wǎng)絡(luò)超時(shí),且當(dāng)客戶端發(fā)生弱網(wǎng))
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ù),開(kāi)啟后臺(tái)任務(wù)
/**
* 無(wú)網(wǎng)絡(luò)提交本地?cái)?shù)據(jù)庫(kù)
* */
private fun insertLocalDB() {
val record = Record('','','',...)
//插入數(shù)據(jù)
PmpDataBase.getInstance(baseContext).planDao().insertRecord(record)
//判斷是否已開(kāi)啟后臺(tái)服務(wù)
val hasLocalRecord: Boolean = MMKVUtil.decodeBoolean(Constants.SP_KEY_LOCAL_RECORD)!!
LogUtils.d("RecordLocalRecord", hasLocalRecord)
if (!hasLocalRecord) {
//沒(méi)開(kāi)啟就去開(kāi)啟
MMKVUtil.encode(Constants.SP_KEY_LOCAL_RECORD, true)
val request = OneTimeWorkRequest.Builder(RecordWorker::class.java)
.setConstraints(getConstraints())
.build()
//隊(duì)列
WorkManager.getInstance(this@CycleEffectActivity).enqueue(request)
WorkManager.getInstance(this@CycleEffectActivity)
.getWorkInfoByIdLiveData(request.id)
.observe(this@CycleEffectActivity, {//通過(guò)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) // 網(wǎng)絡(luò)狀態(tài)
.setRequiresBatteryNotLow(true) // 不在電量不足時(shí)執(zhí)行
.setRequiresCharging(true) // 在充電時(shí)執(zhí)行
.setRequiresStorageNotLow(true) // 不在存儲(chǔ)容量不足時(shí)執(zhí)行
.setRequiresDeviceIdle(true) // 在待機(jī)狀態(tài)下執(zhí)行,須要 API 23
.build()
}
Step2.后臺(tái)任務(wù)調(diào)度(WorkManager)
無(wú)論應(yīng)用程序進(jìn)程是否存在,WorkManager都會(huì)處理在滿足各種約束條件時(shí)需要運(yùn)行的后臺(tái)工作。
后臺(tái)工作可以在應(yīng)用程序位于后臺(tái)、前臺(tái)或者應(yīng)用在前臺(tái)打開(kāi)即將轉(zhuǎn)到后臺(tái)的時(shí)候啟動(dòng)。
無(wú)論應(yīng)用程序在做什么,后臺(tái)工作都應(yīng)該繼續(xù)進(jìn)行,或者在 Android 終止其進(jìn)程時(shí)重啟其后臺(tái)工作。
WorkManager設(shè)計(jì)用于在滿足某些條件時(shí)執(zhí)行操作(e.g.:有網(wǎng)絡(luò)狀態(tài)時(shí),不在電量不足時(shí)執(zhí)行,在充電時(shí)執(zhí)行等)
/**
* @作者 : JayGengi
* @時(shí)間 : 2022/3/17 9:38
* @描述 : 記錄【record】后臺(tái)任務(wù):本地room db文件 記錄內(nèi)容提交服務(wù)器
*/
class RecordWorker(var context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
override fun doWork(): Result {
//接收傳遞過(guò)來(lái)的數(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()
}
}