前段时间做冷启动优化,刚好也很久没写博文了,觉得还是很有必要记录下。
一.常规 *** 作public class MainActivity extends Activity { private static final Handler sHandler = new Handler(Looper.getMainLooper()); @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); sHandler.postDelay(new Runnable() { @OverrIDe public voID run() { // 页面启动所需耗时初始化 doSomething(); } }, 200); }}
大部分开发者在遇到页面冷启动耗时初始化时,会首先考虑通过Handler.postDelay()方法延迟执行。但延迟多久合适?100ms?500ms?还是1s?
延迟过晚,可能会有体验问题;延迟过早,对冷启动没效果。延迟的时间(比如200ms)在三星手机上测试时没问题,换了在华为手机试了就有问题了,然后就围绕着机型的适配不断调整延迟的时间,试图寻找最合适的值,结果发现根本就是不可能的。
二.起始终止点先来看一张图
上图是Google提供的冷启动流程图,可以看到冷启动的起始点时Application.onCreate()方法,结束点在ActivityRecord.reportLanuchTimeLocked()方法。
我们可以通过以下两种方式查看冷启动的耗时
1.查看Logcat在 AndroID Studio Logcat 过滤关键字 “displayed”,可以查看到如下日志:
2019-07-03 01:49:46.748 1678-1718/? I/ActivityManager: displayed com.tencent.qqmusic/.activity.AppStarteractivity: +12s449ms
后面的12s449ms就是冷启动耗时
2.adb dump通过终端执行“adb shell am start -W -S <包名/完整类名> ”
“ThisTime:1370”即为本次冷启动耗时(单位ms)
三、寻找有效结束回调上面知道,冷启动计时起始点是Application.onCreate(),结束点是ActivityRecord.reportLanuchTimeLocked(),但这不是我们可以写业务写逻辑的地方啊,大部分应用业务都以Activity为载体,那么结束回调在哪?
1.IDleHandler从冷启动流程图看,结束时间是在UI渲染完计算的,所以很明显,Activity生命周期中的onCreate()、onResume()、onStart()都不能作为冷启动的结束回调。
常规 *** 作中用Handler.postDelay()问题在于Delay的时间不固定,但我们知道消息处理机制中,MessageQueue有个ArrayList<IDleHandler>
public final class MessageQueue { Message mMessages; priavte final ArrayList<IDleHandler> mIDelHandlers = new ArrayList<IDelHandler>(); Message next() { ... int pendingIDelHandlerCount = -1; // -1 only during first iteration for(;;) { ... // If first time IDle, then get the number of IDlers to run. // IDle handles only run if the queue is empty or if the first message // in the queue (possibly a barrIEr) is due to be handled in the future. if (pendingIDleHandlerCount < 0 && (mMessages == null || Now < mMessages.when)) { pendingIDleHandlerCount = mIDleHandlers.size(); } if (pendingIDleHandlerCount <= 0) { // No IDle handlers to run. Loop and wait some more. mBlocked = true; continue; } // Run the IDle handlers. // We only ever reach this code block during the first iteration. for (int i = 0; i < pendingIDleHandlerCount; i++) { final IDleHandler IDler = mPendingIDleHandlers[i]; mPendingIDleHandlers[i] = null; // release the reference to the handler boolean keep = false; try { keep = IDler.queueIDle(); } catch (Throwable t) { Log.wtf(TAG, "IDleHandler threw exception", t); } } ... } }}
可以在列表中添加IDle任务,IDle任务列表只有Messagequeue队列为空时才会执行,也就是所在线程任务已经执行完时,线程处于空闲状态时才会执行IDle列表中的任务。
冷启动过程中,在Activity.onCreate()中将耗时初始化任务放置到IDle中
public class MainActivity extends Activity { private static final Handler sHandler = new Handler(Looper.getMainLooper()); @OverrIDe protected voID onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentVIEw(R.layout.activity_main); Looper.myQueue().addIDleHandler(new MessageQueue.IDleHandler() { @OverrIDe public boolean queueIDle() { // 页面启动所需耗时初始化 doSomething(); return false; }}); }}
正常情况下,初始化任务是在UI线程所有任务执行完才开始执行,且该方案也不用考虑机型问题。但有个问题,如果UI线程的任务一直不执行完呢?会有这情况?举个 总结
以上是内存溢出为你收集整理的Android开发:关于Android冷启动优化(从3.63%降到0.95%)全部内容,希望文章能够帮你解决Android开发:关于Android冷启动优化(从3.63%降到0.95%)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)