Prefacio
El sábado pasado, comí la comida equivocada, repentinamente mareado, fiebre, vómitos repentinos en medio de la noche, diarrea, toda la persona estaba bastante agitada. Fui al hospital para un examen y dije que fue causado por enteritis xx y por comer la comida equivocada, me quedé en casa y descansé cuatro días.
Hoy, finalmente llegó. Actualice el último artículo de la serie de gráficos acíclicos dirigidos a la optimización de inicio de Android. Recientemente, los artículos en esta área no se actualizarán por el momento. La serie de artículos se resume a continuación:
Optimización de inicio de Android (1): gráfico acíclico dirigido
Optimización de inicio de Android (3) -Instrucciones de AnchorTask
Optimización de inicio de Android (4): enséñele cómo implementar AnchorTask
Notas de lanzamiento
- Versión preconfigurada anterior a las tareas dependientes 0.1.0, por
AnchorTask getDependsTaskList
cierto, ha terminadoclassName
para encontrarAnchorTask
y cohesión en el AnchorTask actual, desde un punto de vista global, este enfoque no es muy intuitivo, 1.0.0 abandonó formas, AliAlpha
camino de referencia a travésaddTask(TASK_NAME_THREE).afterTask(TASK_NAME_ZERO, TASK_NAME_ONE)
- La versión 1.0.0 agrega la clase Project y aumenta la
OnProjectExecuteListener
escucha OnGetMonitorRecordCallback
Monitor de la nueva versión 1.0.0 , facilita las estadísticas de cada tarea lleva
Descripción
Optimización de inicio de Android, puede pensar en la carga asincrónica por primera vez. Coloque las tareas que requieren mucho tiempo en el subproceso para cargar y luego ingrese a la página de inicio después de que se carguen todas las tareas de carga.
El esquema de carga asíncrono de subprocesos múltiples está bien. Pero, ¿qué pasa si se encuentra con una relación de dependencia? Por ejemplo, la tarea 2 depende de la tarea 1. ¿Cómo resolverla en este momento?
Supongamos que tenemos tal dependencia de tareas
Cómo lo usamos
val project =
AnchorProject.Builder().setContext(context).setLogLevel(LogUtils.LogLevel.DEBUG)
.setAnchorTaskCreator(ApplicationAnchorTaskCreator())
.addTask(TASK_NAME_ZERO)
.addTask(TASK_NAME_ONE)
.addTask(TASK_NAME_TWO)
.addTask(TASK_NAME_THREE).afterTask(TASK_NAME_ZERO, TASK_NAME_ONE)
.addTask(TASK_NAME_FOUR).afterTask(TASK_NAME_ONE, TASK_NAME_TWO)
.addTask(TASK_NAME_FIVE).afterTask(TASK_NAME_THREE, TASK_NAME_FOUR)
.build()
project.start().await()
复制代码
class ApplicationAnchorTaskCreator : IAnchorTaskCreator {
override fun createTask(taskName: String): AnchorTask? {
when (taskName) {
TASK_NAME_ZERO -> {
return AnchorTaskZero()
}
TASK_NAME_ONE -> {
return AnchorTaskOne()
}
TASK_NAME_TWO -> {
return AnchorTaskTwo()
}
TASK_NAME_THREE -> {
return AnchorTaskThree()
}
TASK_NAME_FOUR -> {
return AnchorTaskFour()
}
TASK_NAME_FIVE -> {
return AnchorTaskFive()
}
}
return null
}
}
复制代码
Cuando se ejecuta la demostración, puede ver el efecto esperado.
Uso basico
Paso 1: configurar dependencias remotas en moulde build.gradle
implementation 'com.xj.android:anchortask:1.0.0'
复制代码
El último número de versión se puede encontrar aquí última versión
Paso dos: personalizado AnchorTaskZero
, heredado AnchorTask
y específico taskName
, la atención taskName
debe ser única, porque estaremos de acuerdo con taskName
el AnchorTask
método correspondiente para encontrar el método de anulación apropiado.
class AnchorTaskZero() : AnchorTask(TASK_NAME_ZERO) {
override fun isRunOnMainThread(): Boolean {
return false
}
override fun run() {
val start = System.currentTimeMillis()
try {
Thread.sleep(300)
} catch (e: Exception) {
}
LogUtils.i(
TAG, "AnchorTaskOne: " + (System.currentTimeMillis() - start)
)
}
}
复制代码
Si la tarea tres depende de la tarea dos y la tarea uno, puede escribir así
addTask(TASK_NAME_THREE).afterTask(TASK_NAME_ZERO, TASK_NAME_ONE)
复制代码
Finalmente, el project.start()
método se inicia, si es necesario bloquear la espera, llamar al método await ()
AnchorProject.Builder().setContext(context).setLogLevel(LogUtils.LogLevel.DEBUG)
.setAnchorTaskCreator(ApplicationAnchorTaskCreator())
.addTask(TASK_NAME_ZERO)
.addTask(TASK_NAME_ONE)
.addTask(TASK_NAME_TWO)
.addTask(TASK_NAME_THREE).afterTask(TASK_NAME_ZERO, TASK_NAME_ONE)
.addTask(TASK_NAME_FOUR).afterTask(TASK_NAME_ONE, TASK_NAME_TWO)
.addTask(TASK_NAME_FIVE).afterTask(TASK_NAME_THREE, TASK_NAME_FOUR)
.build()
project.start().await()
复制代码
Supervisar devolución de llamada de tarea
project.addListener(object : OnProjectExecuteListener {
// project 开始执行的时候
override fun onProjectStart() {
com.xj.anchortask.LogUtils.i(MyApplication.TAG, "onProjectStart ")
}
// project 执行一个 task 完成的时候
override fun onTaskFinish(taskName: String) {
com.xj.anchortask.LogUtils.i(
MyApplication.TAG,
"onTaskFinish, taskName is $taskName"
)
}
// project 执行完成的时候
override fun onProjectFinish() {
com.xj.anchortask.LogUtils.i(MyApplication.TAG, "onProjectFinish ")
}
})
复制代码
Agregue una devolución de llamada que requiere mucho tiempo para cada ejecución de tarea
project.onGetMonitorRecordCallback = object : OnGetMonitorRecordCallback {
// 所有 task 执行完毕会调用这个方法,Map 存储了 task 的执行时间, key 是 taskName,value 是时间,单位毫秒
override fun onGetTaskExecuteRecord(result: Map<String?, Long?>?) {
onGetMonitorRecordCallback?.onGetTaskExecuteRecord(result)
}
// 所有 task 执行完毕会调用这个方法,costTime 执行时间
override fun onGetProjectExecuteTime(costTime: Long) {
onGetMonitorRecordCallback?.onGetProjectExecuteTime(costTime)
}
}
复制代码
Introducción al AnchorProject
AnchorTaskDispatcher start
El método debe llamarse en el subproceso principal y las llamadas al subproceso arrojarán una excepción.await
Bloquea el hilo actual, espera a que se ejecuten todas las tareas y luego baja automáticamente, el método de espera lleva un parámetro, timeOutMillion representa el tiempo de espera de tiempo de esperaawait()
El método debe llamarse después del método de inicio- Agregar una tarea
AnchorProject.Builder().addTask
agregando un modo de configuración típico - Configure el grupo de subprocesos para la ejecución, puede pasar
AnchorProject.Builder().setThreadPoolExecutor(TaskExecutorManager.instance.cpuThreadPoolExecutor)
Introducción a AnchorTask
AnchorTask implementa la interfaz IAnchorTask, hay varios métodos principales
isRunOnMainThread(): Boolean
Indica si se ejecutará en el hilo principal, el valor predeterminado es falsopriority(): Int
El método indica el nivel de prioridad del hilo, el valor predeterminado es Process.THREAD_PRIORITY_FOREGROUNDneedWait()
Significa que cuando llamamosAnchorTaskDispatcher await
, si esperar, devolver verdadero, expresó la necesidad de esperar al final para cambiar la ejecución de la tarea,AnchorTaskDispatcher await
el método puede continuar con la implementación.fun run()
Método, que significa cuándo se ejecuta la tarea
interface IAnchorTask : IAnchorCallBack {
/**
* 是否在主线程执行
*/
fun isRunOnMainThread(): Boolean
/**
* 任务优先级别
*/
@IntRange(
from = Process.THREAD_PRIORITY_FOREGROUND.toLong(),
to = Process.THREAD_PRIORITY_LOWEST.toLong()
)
fun priority(): Int
/**
* 调用 await 方法,是否需要等待改任务执行完成
* true 不需要
* false 需要
*/
fun needWait(): Boolean
/**
* 任务被执行的时候回调
*/
fun run()
}
复制代码
class AnchorTaskOne : AnchorTask() {
override fun isRunOnMainThread(): Boolean {
return false
}
override fun run() {
val start = System.currentTimeMillis()
try {
Thread.sleep(300)
} catch (e: Exception) {
}
LogUtils.i(
TAG, "AnchorTaskOne: " + (System.currentTimeMillis() - start)
)
}
}
复制代码
La devolución de llamada de la tarea de supervisión
val anchorTask = AnchorTaskTwo()
anchorTask.addCallback(object : IAnchorCallBack {
override fun onAdd() {
com.xj.anchortask.LogUtils.i(TAG, "onAdd: $anchorTask")
}
override fun onStart() {
com.xj.anchortask.LogUtils.i(TAG, "onStart:$anchorTask ")
}
override fun onFinish() {
com.xj.anchortask.LogUtils.i(TAG, "onFinish:$anchorTask ")
}
})
复制代码
para resumir
El principio de AnchorTask no es complicado, y la esencia es la combinación de un gráfico acíclico dirigido y conocimiento multiproceso.
- Construya un gráfico acíclico dirigido según BFS y obtenga su clasificación topológica
- En el proceso de ejecución multiproceso, aseguramos la relación de ejecución secuencial a través de la relación de subtarea de la tarea y CounDownLatch
- Si la tarea predecesora no se ha ejecutado, espere, si la ejecución se ha completado, baje
- Realizar tareas
- Notifique a la subtarea que la tarea actual se completó y el contador correspondiente (en grados) debería reducirse en uno.
Más desarrollo de Android bienvenido a unirse a nuestro círculo de aprendizaje avanzado de Android