使用WorkManager
def versions = "2.7.1"
implementation "androidx.work:work-runtime:$versions"
简单示例,并对重要方法做说明
object TsmWorkManagerTest {
private const val TAG_WORKER="tsm_work_tag"
@JvmStatic
fun tsmWorkManger(context: Context){
/**
* 重点-->1
* WorkManager 自身维护了一套数据库,所以已经添加的任务即使进程结束了,
* 在下一次App启动时,也会自动启用,也就是同一个任务如果没有必要,我们是不用添加第二次的,
* 所以为了避免同一个周期任务被多次添加,可以使用
* WorkManager.getInstance(context.applicationContext)
* .enqueueUniquePeriodicWork("MyUniqueWorkName",ExistingPeriodicWorkPolicy.KEEP,myWork)
* 来添加周期性的任务,
* 参数1->MyUniqueWorkName 任务名称,开发者自定义,这个方法就是通过这个字段来区别是否是同一个任务,不关注任务名称
* 参数2->ExistingPeriodicWorkPolicy.KEEP keep 的含义是当第二个周期性任务来临时,保持原有任务,放弃新的任务 同时还有replace
* 参数3->myWork 任务
*
*
* 重点-->2
* 调用 WorkManager.getInstance(context.applicationContext).cancelAllWorkByTag 后
* 再次获取任务的个数还是之前的个数,也就是 cancel 只是让任务不能执行了,并没有将任务从
* 任务队列中移除,
*/
var workers= WorkManager.getInstance(context.applicationContext).getWorkInfosByTag(
TAG_WORKER
)
TsmLogUtils.i("任务个数:${workers.get().size}")
if(workers.get().size ==0){
var builder= Constraints.Builder()
builder.setRequiredNetworkType(NetworkType.CONNECTED)//有网
.setRequiresBatteryNotLow(true)//电量充足
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// builder.setRequiresDeviceIdle(true)//空闲
// }
//20秒执行一次,弹性5秒执行
val uploadWorkRequest = PeriodicWorkRequest.Builder(TsmWorker::class.java, 5, TimeUnit.SECONDS)
.setConstraints(builder.build())
.addTag(TAG_WORKER)
.build()
//
WorkManager.getInstance(context.applicationContext).enqueue(uploadWorkRequest)
}else{
TsmLogUtils.i("任务状态:${workers.get()[0].state}")
}
//上面的是通过判断个数来执行的,但是这么操作对于一个周期性任务是不可控的,那么我们如何来避免呢,
//答案就是上面的重点1中介绍的enqueueUniquePeriodicWork 这个方法
}
}
class TsmWorker : Worker {
/**
* 这个是用来判断每次执行的时候是否是同一个worker,
* 通过验证得到的答案是否定的,每次重新执行都是一个不同的对象,应该是反射生成的
*/
private var tsm_tag:Int= Random().nextInt(50)
constructor(context: Context,workerParameters: WorkerParameters):super(context,workerParameters)
override fun doWork(): Result {
TsmLogUtils.i("定期任务$tsm_tag:-->${formatTime()} 是否是主线程:${Looper.getMainLooper() == Looper.myLooper()}")
return Result.success()
}
private fun formatTime():String{
return SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date(System.currentTimeMillis()))
}
}