在优化之前首先得有一个量化的过程,不然很难知道我们的优化有没有结果,不能总是靠感觉,就像看大师炒菜,大师告诉你放适量的盐一样蛋疼。
工具选择
知道了启动和页面渲染的时间我们还得去找具体的位置,要是顺便能定位位置就好了 ,抱着这种心态,一开始我就瞄准的第三方的开源库,大概找了下有腾讯的# Matrix和360的# ArgusAPM。但看到GitHub上的上次更新时间,瞬间有种情况不是很乐观的感觉。
尤其是360这个,去年开源,上次更新就是9月前,跟不维护差不多了,再去issue里看看,情况真的不容乐观:
瞬间感觉自己摊上大事了,我还只是个孩纸啊,行吧,我们再去看看腾讯大哥的Matrix吧
大哥就是大哥,那还等啥,撸吧。
一顿操作猛如虎,一看BUG有2个痛点
1.没办法像Matrix的demo那样统计启动之类的时间,因为工程用的是AndroidX
2.每次修改类都需要clean一次工程,这个很耗时间啊
看了下issue,发现不少反馈这样的问题,都没有得到官方正式的回复,哎,好难,没办法只能自己搞了。
自己写简陋版时间统计
自己搞虽然没有Matrix这样可以很快的定位到问题,但也是有自己的优势的,比如编译快。加入Matrix的Trace模块可以明显感受到编译慢了很多要1m18s,而正常调试编译的时候只需要38s左右,这是因为编译期间trace模块会会自动在每个方法是开始和结束加入时间统计的标识,这样方便我们定位问题。
主要统计的就是application创建时间、启动页(Splash)时间、第一个Activity渲染完成的时间。
最近负责项目的启动顺序
application初始化一些库=》Splash(一个)=》MainActivity(FirstActivity)
当前Activity加载完成的标志是参考Matrix里的代码,发现在Activity的onWindowFocusChange()里面有特别的插桩代码,源码里的注释也证实了观点,之所以不支持AndroidX,估计就是忘了在对应的地方插代码了
统计Activity页面加载时间
因为有BaseActivity,所以从这着手,在onCreate时记录,在第一次获得焦点时结束,统计时间差,大概就是Activity的页面加载时间了
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
timeOnCreate = System.currentTimeMillis();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (isFirstFocus && hasFocus){
TraceHelper.get().onWindowFocusChange(tag,System.currentTimeMillis()-timeOnCreate);
isFirstFocus=false;
}
}
统计一次冷启动时间
application创建时间=splashOnCreate()-start()
Splash渲染时间=onWindowFocusChange()-onCreate()
Splash停留的时间=mainActivityOnCreate()-splashOnCreate()
MainActivity渲染时间=onWindowFocusChange()-onCreate()
冷启动时间=MainActivityonWindowFocusChange()-applicationOnCreate()
自己项目的统计效果:测试机器Redmi5(骁龙450+3gRAM),缺少了Splash的页面渲染时间,而我在oncreat方法里面就设置了跳转,推测是这样没有获得焦点,MainActivity有3秒,有很大优化空间了
统计方法时间
通过上面的过程,我们得到了一个总体的时间,我们想细化定位的话还得知道这个过程里方法执行的时间,由于方法数比较多,而且方法统计在整个项目都有用到的地方,肯定就不能再像上面那样自己写了,由于时间紧我还没有找到一个合适的第三方库,只能等Matrix修复或者你们有更好的也可以在评论里分享一下
最后附上本次的工具类:
/**
* create by z on 19/12/27
*
* @author z
*/
public class TraceHelper {
private boolean isEnable = true;
private static TraceHelper instance;
private long startTime;
private long splashOnCreateTime;
private long mainActivityTime;
private long completeTime;
private Map activityRenderTimes=new HashMap<>();
private TraceHelper() {
}
public static TraceHelper get() {
if (instance == null) {
synchronized (TraceHelper.class) {
if (instance == null) {
instance = new TraceHelper();
}
}
}
return instance;
}
private long getTime(){
return System.currentTimeMillis();
}
public void start() {
startTime = getTime();
}
public void splashOnCreate() {
splashOnCreateTime = getTime();
}
public void mainActivity(){
mainActivityTime = getTime();
}
@SuppressLint("DefaultLocale")
public void onWindowFocusChange(String tag, long timeMist) {
Log4jUtils.d(this,String.format("onWindowFocusChange--tag[%s]-----time[%d]",tag,timeMist));
activityRenderTimes.put(tag,timeMist);
//冷启动时间
if (tag.contains("MainActivity")){
complete();
}
}
private void complete(){
if (isEnable){
completeTime=getTime();
show();
}
}
public void show(){
Log4jUtils.d(this,"------------------------------------------------");
Log4jUtils.d(this,"--applicationCreateTime: "+(splashOnCreateTime-startTime));
Log4jUtils.d(this,"--SplashStayTime: "+(mainActivityTime -splashOnCreateTime));
Log4jUtils.d(this,"--completeTime: "+(completeTime-startTime));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
activityRenderTimes.forEach((s, aLong) -> {
Log4jUtils.d(this,"--"+s+": "+aLong);
});
}
Log4jUtils.d(this,"------------------------------------------------");
}
}