package com.noahedu.myapplication;
import android.app.Application;
import android.os.Debug;
import android.util.Log;
/**
- @Description: java类作用描述
- @Author: huangjialin
- @CreateDate: 2020/7/10 9:59
*/
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Debug.startMethodTracing(“MyApplication”);
taskOne();
taskTwo();
taskThrid();
taskFour();
Debug.stopMethodTracing();
}
public void taskOne(){
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void taskTwo(){
try {
Thread.sleep(2050);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void taskThrid(){
try {
Thread.sleep(350);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void taskFour(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
现在application的onCreate方法中有几个任务,各个耗时是不一样的。可能很多同学就会说了,异步处理啊,开线程,放到线程池中,或者创建一个IntentService来执行。那么我们就要考虑几个问题了
第一:异步处理,如果在某个页面需要用到某个SDK,但是又没有初始化完成呢?
第二:假如说taskTwo需要taskOne的某个返回值呢?怎么保证taskOne在taskTwo之前执行完毕呢?
第三:开线程,开多少个线程呢?多了会造成资源浪费,少了资源又没有合理的利用。
我个人觉得针对于启动优化,在Application中的onCreate()进行初始化任务操作,我们首先需要对这些任务进行一个优先级划分,针对于那些优先级高的任务,我们可以优先进行处理,对于那些优先级较低的,我们可以适当的延迟进行加载。
其次有很多同学喜欢把那些优先级较低的任务进行延迟加载,比如new Handler().postDelayed()
,这种我觉得是非常不可取的,假如说放在postDelayed中的任务耗时2s,延迟1s进行处理,那么在执行2s任务的过程中,有用户进行操作,那岂不是很卡吗,很明显,这是指标不治本的。
7.1 启动器的思想
针对上面说的几个痛点,怎么在处理上面的几个痛点,又能保证代码的可维护性呢?换句话说就是一个新人不需要理解整个过程,直接就可以开干呢?那么,启动器来了。
启动器核心思想:充分利用CPU多核,自动梳理任务顺序
7.2 启动器的原理
1、任务全部封装成Task对象,传入到集合中。
2、根据所有的任务依赖关系,形成一个有向无环图,然后通过拓扑排序排列出任务的执行流程
3、通过CountDownLatch来控制某一个任务是否执行完毕才进行下一步。
4、线程池创建核心线程的数量,由手机的核数量决定的。
7.3启动器使用方式
7.4启动器核心代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8m4xnqLS-1651119006927)(https://upload-images.jianshu.io/upload_images/14140248-77b667b632cbd79c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
进行任务排序
package com.noahedu.launchertool.launchstarter.sort;
import com.noahedu.launchertool.launchstarter.task.Task;
import com.noahedu.launchertool.launchstarter.utils.DispatcherLog;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import androidx.annotation.NonNull;
import androidx.collection.ArraySet;
public class TaskSortUtil {
private static List sNewTasksHigh = new ArrayList<>();// 高优先级的Task
/**
- 任务的有向无环图的拓扑排序
- @return
*/
public static synchronized List getSortResult(List originTasks,
List<Class<? extends Task>> clsLaunchTasks) {
long makeTime = System.currentTimeMillis();
Set dependSet = new ArraySet<>();
Graph graph = new Graph(originTasks.size());
for (int i = 0; i < originTasks.size(); i++) {
Task task = originTasks.get(i);
if (task.isSend() || task.dependsOn() == null || task.dependsOn().size() == 0) {
continue;
}
for (Class cls : task.dependsOn()) {
int indexOfDepend = getIndexOfTask(originTasks, clsLaunchTasks, cls);
if (indexOfDepend < 0) {
throw new IllegalStateException(task.getClass().getSimpleName() +
" depends on " + cls.getSimpleName() + " can not be found in task list ");
}
dependSet.add(indexOfDepend);
graph.addEdge(indexOfDepend, i);
}
}
List indexList = graph.topologicalSort();
List newTasksAll = getResultTasks(originTasks, dependSet, indexList);
DispatcherLog.i("task analyse cost makeTime " + (System.currentTimeMillis() - makeTime));
printAllTaskName(newTasksAll);
return newTasksAll;
}
@NonNull
private static List getResultTasks(List originTasks,
Set dependSet, List indexList) {
List newTasksAll = new ArrayList<>(originTasks.size());
List newTasksDepended = new ArrayList<>();// 被别人依赖的
List newTasksWithOutDepend = new ArrayList<>();// 没有依赖的
List newTasksRunAsSoon = new ArrayList<>();// 需要提升自己优先级的,先执行(这个先是相对于没有依赖的先)
for (int index : indexList) {
if (dependSet.contains(index)) {
newTasksDepended.add(originTasks.get(index));
} else {
Task task = originTasks.get(index);
if (task.needRunAsSoon()) {
newTasksRunAsSoon.add(task);
} else {
newTasksWithOutDepend.add(task);
}
}
}
// 顺序:被别人依赖的————》需要提升自己优先级的————》需要被等待的————》没有依赖的
sNewTasksHigh.addAll(newTasksDepended);
sNewTasksHigh.addAll(newTasksRunAsSoon);
newTasksAll.addAll(sNewTasksHigh);
newTasksAll.addAll(newTasksWithOutDepend);
return newTasksAll;
}
private static void printAllTaskName(List newTasksAll) {
if (true) {
return;
}
for (Task task : newTasksAll) {
DispatcherLog.i(task.getClass().getSimpleName());
}
}
public static List getTasksHigh() {
return sNewTasksHigh;
}
/**
- 获取任务在任务列表中的index
- @param originTasks
- @return
*/
private static int getIndexOfTask(List originTasks,
List<Class<? extends Task>> clsLaunchTasks, Class cls) {
int index = clsLaunchTasks.indexOf(cls);
if (index >= 0) {
return index;
}
// 仅仅是保护性代码
final int size = originTasks.size();
for (int i = 0; i < size; i++) {
if (cls.getSimpleName().equals(originTasks.get(i).getClass().getSimpleName())) {
return i;
}
}
return index;
}
}
执行任务代码
package com.noahedu.launchertool.launchstarter.task;
import android.os.Looper;
import android.os.Process;
import com.noahedu.launchertool.launchstarter.TaskDispatcher;
import com.noahedu.launchertool.launchstarter.stat.TaskStat;
import com.noahedu.launchertool.launchstarter.utils.DispatcherLog;
/**
- 任务真正执行的地方
*/
public class DispatchRunnable implements Runnable {
private Task mTask;
private TaskDispatcher mTaskDispatcher;
public DispatchRunnable(Task task) {
this.mTask = task;
}
public DispatchRunnable(Task task,TaskDispatcher dispatcher) {
this.mTask = task;
this.mTaskDispatch 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】 er = dispatcher;
}
@Override
public void run() {
DispatcherLog.i(mTask.getClass().getSimpleName()
- " begin run" + " Situation " + TaskStat.getCurrentSituation());
Process.setThreadPriority(mTask.priority());
long startTime = System.currentTimeMillis();
mTask.setWaiting(true);
mTask.waitToSatisfy();
long waitTime = System.currentTimeMillis() - startTime;
startTime = System.currentTimeMillis();
// 执行Task
mTask.setRunning(true);
mTask.run();
// 执行Task的尾部任务
Runnable tailRunnable = mTask.getTailRunnable();
if (tailRunnable != null) {
tailRunnable.run();
}
if (!mTask.needCall() || !mTask.runOnMainThread()) {
printTaskLog(startTime, waitTime);
TaskStat.markTaskDone();
mTask.setFinished(true);
if(mTaskDispatcher != null){
mTaskDispatcher.satisfyChildren(mTask);
mTaskDispatcher.markTaskDone(mTask);
}
DispatcherLog.i(mTask.getClass().getSimpleName() + " finish");
}
}
/**
- 打印出来Task执行的日志
- @param startTime
- @param waitTime
*/
private void printTaskLog(long startTime, long waitTime) {
long runTime = System.currentTimeMillis() - startTime;
if (DispatcherLog.isDebug()) {
DispatcherLog.i(mTask.getClass().getSimpleName() + " wait " + waitTime + " run "
- runTime + " isMain " + (Looper.getMainLooper() == Looper.myLooper())
- " needWait " + (mTask.needWait() || (Looper.getMainLooper() == Looper.myLooper()))
- " ThreadId " + Thread.currentThread().getId()
- " ThreadName " + Thread.currentThread().getName()
- " Situation " + TaskStat.getCurrentSituation()
Looper.getMainLooper() == Looper.myLooper()) - " needWait " + (mTask.needWait() || (Looper.getMainLooper() == Looper.myLooper()))
- " ThreadId " + Thread.currentThread().getId()
- " ThreadName " + Thread.currentThread().getName()
- " Situation " + TaskStat.getCurrentSituation()