-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Description
object InitTaskService : CoroutineScope by MainScope() {
private lateinit var taskList: MutableList<TaskInfo>
private var collectTaskList: MutableList<AutoInitTask>? = null
private val listenerMap by lazy {
ArrayMap<String, ITaskStateChangeListener>()
}
private var completeListener: ITaskCompleteListener? = null
private var stateChangeListener: ITaskStateChangeListener? = null
private var currentProcessName: String? = null
@Volatile
private var started = false
private var taskTotal = 0
private var counter = 0
fun callbackOnTaskComplete(listener: ITaskCompleteListener) {
synchronized(listenerMap) {
this.completeListener = listener
}
}
fun callbackOnTaskState(listener: ITaskStateChangeListener) {
synchronized(listenerMap) {
this.stateChangeListener = listener
}
}
/**
* 判断任务是否执行完毕
*/
fun taskIsFinished(name: String): Boolean {
return getTaskInfoByName(name)?.isDone() == true
}
/**
* 所有任务是否执行完毕
*/
fun allTaskIsFinished() = counter == taskTotal
/**
* 监听某一任务进度
*/
fun registerTaskStateCallback(name: String, callback: ITaskStateChangeListener) {
synchronized(listenerMap) {
getTaskInfoByName(name)?.also {
callback.onChanged(it)
if (it.isDone()) {
return
}
}
listenerMap[name] = callback
}
}
/**
* 监听某一任务进度
*/
fun unregisterTaskFinishCallback(name: String) {
synchronized(listenerMap) {
listenerMap.remove(name)
}
}
/**
* 开始任务
*/
fun startInitTask(application: Application, vararg registerTasks: ITaskInitExecute<*>) {
if (started) {
return
}
started = true
autoCollectTask()
val collectSize = requireNotNull(collectTaskList).size
val tempRegisterTask: ArrayMap<String, TaskInfo> = ArrayMap()
val collectTaskMap: ArrayMap<String, AutoInitTask> = ArrayMap()
val processName = currentProcessName(application)
val noDependList = ArrayList<AutoInitTask>(collectSize)
val dependList = ArrayList<AutoInitTask>(collectSize)
requireNotNull(collectTaskList).forEach {
val taskInfo = it.taskInfo
if (collectTaskMap.contains(taskInfo.name)) {
throw IllegalArgumentException("task name 不能重复:${taskInfo.name}")
}
if (!isMatchProcessByTask(application, processName, taskInfo.process)) {
return@forEach
}
tempRegisterTask[taskInfo.taskIdentity] = taskInfo
if (it.task != null) {
collectTaskMap[taskInfo.name] = it
if (taskInfo.depends.isNullOrEmpty()) {
noDependList.add(it)
dispatchTaskProgress(taskInfo, TaskState.READY)
} else {
dependList.add(it)
}
taskList.add(taskInfo)
}
}
registerTasks.forEach {
val taskInfo = requireNotNull(tempRegisterTask[it.javaClass.name]) {
"请使用@TaskProps注解标记Task: $it"
}
if (collectTaskMap.contains(taskInfo.name)) {
throw IllegalArgumentException("task name 不能重复:${taskInfo.name}")
}
if (!isMatchProcessByTask(application, processName, taskInfo.process)) {
return@forEach
}
val initTask = AutoInitTask(taskInfo, it)
collectTaskMap[taskInfo.name] = initTask
if (taskInfo.depends.isNullOrEmpty()) {
noDependList.add(initTask)
dispatchTaskProgress(taskInfo, TaskState.READY)
} else {
dependList.add(initTask)
}
taskList.add(taskInfo)
}
/**
* 释放引用
*/
collectTaskList?.clear()
collectTaskList = null
taskTotal = taskList.size
dependList.forEach {
val taskInfo = it.taskInfo
taskInfo.depends?.forEach { pName ->
checkAndBindSubTask(collectTaskMap, pName, taskInfo.name)
dispatchTaskProgress(taskInfo, TaskState.READY)
}
}
noDependList.sortedDescending().forEach {
launch(Dispatchers.Main.immediate) {
executeTask(collectTaskMap, application, it, processName)
}
}
}
/**
* AutoRegister 自动注入
*/
private fun autoCollectTask() {
collectTaskList = mutableListOf()
taskList = mutableListOf()
}
private fun register(register: ModuleTaskRegister) {
register.register(requireNotNull(collectTaskList))
}
private fun currentProcessName(application: Application): String {
return currentProcessName ?: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Application.getProcessName()
} else {
val pid = Process.myPid()
(application.getSystemService(Context.ACTIVITY_SERVICE) as? ActivityManager)?.runningAppProcesses?.find {
it.pid == pid
}?.processName
}?.also {
currentProcessName = it
}.orEmpty()
}
private fun isMatchProcessByTask(application: Application, processName: String, process: Array<String>?): Boolean {
if (process.isNullOrEmpty()) {
return true
}
if (process.size == 1) {
val singleElement = process[0]
if (singleElement == TaskProps.PROCESS_ALL) {
return true
}
if (singleElement == TaskProps.PROCESS_MAIN && application.packageName == processName) {
return true
}
if (singleElement == TaskProps.PROCESS_WITHOUT_MAIN && application.packageName != processName) {
return true
}
}
return process.contains(processName)
}
private fun checkAndBindSubTask(collectTaskMap: ArrayMap<String, AutoInitTask>, pName: String, cName: String) {
val parentTask = collectTaskMap[pName]
requireNotNull(parentTask) {
"$cName-依赖的父Task-$pName-不存在"
}
if (parentTask.taskInfo.depends?.contains(cName) == true) {
throw IllegalArgumentException("任务存在循环引用:$pName and $cName")
}
parentTask.taskInfo.childTask = parentTask.taskInfo.childTask?.plusElement(cName) ?: arrayOf(cName)
}
@MainThread
private suspend fun executeTask(collectTaskMap: ArrayMap<String, AutoInitTask>, application: Application, autoTask: AutoInitTask, processName: String) {
val taskInfo = autoTask.taskInfo
check(!allTaskIsFinished()) {
"系统异常,校验错误"
}
check(!taskInfo.isDone()) {
"系统异常,任务已经执行过了"
}
val coroutineContext = if (taskInfo.isMainThread) {
EmptyCoroutineContext
} else {
Dispatchers.Default
}
dispatchTaskProgress(taskInfo, TaskState.RUNNING)
val result = withContext(coroutineContext) {
(autoTask.task as ITaskInitExecute<*>).runCatching {
executeInit(application, processName)
}
}
synchronized(listenerMap) {
taskInfo.result = if (result.isSuccess) {
result.getOrNull()
} else {
result.exceptionOrNull()
}
counter++
dispatchTaskProgress(taskInfo, TaskState.DONE)
if (counter == taskTotal) {
// 所有任务已完成
completeListener?.onCompleted()
completeListener = null
stateChangeListener = null
listenerMap.clear()
return
}
}
taskInfo.childTask?.mapNotNull { cName ->
requireNotNull(collectTaskMap[cName]).takeIf {
requireNotNull(it.taskInfo.depends).all { pName ->
requireNotNull(collectTaskMap[pName]).taskInfo.isDone()
}
}
}?.sortedDescending()?.forEach {
launch(Dispatchers.Main.immediate) {
executeTask(collectTaskMap, application, it, processName)
}
}
}
private fun getTaskInfoByName(name: String): TaskInfo? {
if (!::taskList.isInitialized) {
return null
}
return taskList.find { it.name == name }
}
private fun dispatchTaskProgress(task: TaskInfo, state: TaskState) {
task.state = state
synchronized(listenerMap) {
stateChangeListener?.onChanged(task)
listenerMap[task.name]?.onChanged(task)
}
}
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels