APP启动优化,你应该没看到过这样子的
2020-05-21 本文已影响0人
Sky_Blue
一、检测APP启动耗时
- 用Android系统Debug API 生成文件,记录启动耗时操作。
- 用AndroidStudio Profiler 查看耗时操作排行
生成追踪耗时文件代码如下:
/**
* 运行时间跟踪
*/
public class TrackUtils {
private TrackUtils() {
}
private static class Holder {
private static final TrackUtils instance = new TrackUtils();
}
public static TrackUtils getInstance() {
return Holder.instance;
}
public void start() {
// 追踪启动时间
if (BuildConfig.IS_DEBUG) {
File file = new File(Environment.getExternalStorageDirectory(), "app.trace");
Log.e("start", "start: " + file.getAbsolutePath());
Debug.startMethodTracing(file.getAbsolutePath());
}
}
public void end() {
// 追踪结束时间
if (BuildConfig.IS_DEBUG) {
Debug.stopMethodTracing();
}
}
}
- 使用方式
TrackUtils.getInstance().start();
// ... 初始化内容
TrackUtils.getInstance().end();
-
导出app.trace文件,拖到AdroidStudio查看如图所示
trace.png
- 找到耗时的操作
二、耗时操作处理方式(Kotlin协程处理)
- 经过多次实战测试,用线程池也不行,发现用Kotlin的协程处理最优。
- Kotlin的协程核心思想还是线程,优点:开启线程后挂起操作,不占用主线程的资源,任务执行完后自动切换到主线程。
- 部分三方在线程初始化要注意:Handler消息发送(Looper的操作)。
三、实现代码,要使用Kotlin的代码,不懂Kotlin的自己去了解一下
/**
* 初始化任务类
*/
public abstract class InitTask {
// 要不要开启Looper
private boolean isLooper;
public InitTask() {
this(false);
}
public InitTask(boolean isLooper) {
this.isLooper = isLooper;
}
public void run() {
//设置线程的优先级,不与主线程抢资源
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
if (isLooper) {
Looper.prepare();
}
execute();
if (isLooper) {
Looper.loop();
}
}
public abstract void execute();
}
/**
* 协程工具类:用于APP启动优化
*/
object GlobalScopeUtils {
fun launch(task: InitTask) {
// 主线程开启协程
GlobalScope.launch(Dispatchers.Main) {
// 挂起:在IO线程执行任务
withContext(Dispatchers.IO) {
task.run()
}
// 任务执行完自动切换回到主线程
}
}
}
四、使用协程初始化
- 找出耗时操作,进行分类处理
- 将耗时多的,可以单独放在一个协程里面处理。其它的,根据耗时的时间分组来初始化。
/**
* 用协程初始化
*/
public final void initBackground() {
GlobalScopeUtils.INSTANCE.launch(new InitTask() {
@Override
public void execute() {
// 极光推送
initPush();
// x5内核
initX5();
// 谷歌分析
initAnalytics();
}
});
// 这些三方要开启Looper
GlobalScopeUtils.INSTANCE.launch(new InitTask(true) {
@Override
public void execute() {
// 环信IM
initIM();
// 百度地图
initBaiDuMap();
// 腾讯Bugly
initBugly();
}
});
GlobalScopeUtils.INSTANCE.launch(new InitTask() {
@Override
public void execute() {
// 分享、短信
initMob();
// ReactNative
initSoLoader();
}
});
}