Android-APP启动优化
黑白屏问题优化
黑白屏在商业APP中的价值
如何使用Traceview工具对优化定位处理
伪优化
用于用户体验,用来给到用户体验,没有实质性的优化
案例
注意看这一块(parent=“Theme.AppCompat.Light”)
如果没写这一块,启动时会是一个黑屏,写了这一块,启动时会是一个白屏;
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimarydark</item>
<item name="colorAccent">@color/coloraccent</item>
<!--去掉系统默认的标题栏-->
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<!-- 设置activity切换动画 -->
<item name="android:windowAnimationStyle">@style/activityAnimation</item>
</style>
相信很多人,经常在Application中做一些初始化,这样会造成启动时白屏的时间延长,有些好的手机上面可能发现不了,我们这里就做了个延时3秒来模拟下;
注意看下面的GIF图,在冷启动时点击启动app的时候,注意看启动时的白屏;
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
File file = new File(Environment.getExternalStorageDirectory(), "app1.trace");
Log.i(TAG, "onCreate: " + file.getAbsolutePath());
//把分析结果存在一个文件
Debug.startMethodTracing(file.getAbsolutePath());
//对全局属性赋值
mContext = getApplicationContext();
mMainThread = Thread.currentThread();
mMainThreadId = android.os.Process.myTid();
mMainLooper = getMainLooper();
mHandler = new Handler();
try {
//这里来模拟做一些初始化工作
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
NIMClient.init(this, loginInfo(), options());
Debug.stopMethodTracing();
}
}
这一块白屏是不是很难看?
注: 这个不是微信,这个是我在码云上面下载的一个模仿微信的项目哦;
以前都会觉得是个很难看的bug,现在很多软件会利用这个白屏时间,显示一张背景图;
占位图方案
我想大家应该知道parent就是父类吧,也是继承的样式吧 ?
我们跟着这个parent="Theme.AppCompat.Light"父类,一层一层的往下找;
最终看到这个(Platform.AppCompat.Light)样式
android:windowBackground:看名字应该知道吧,窗口背景;
<style name="Platform.AppCompat.Light" parent="android:Theme.Light">
......
<item name="android:windowBackground">@color/background_material_light</item>
......
</style>
我们来修改这个android:windowBackground ,注意不是在这个里面直接修改!!!
我们在自己的主题里面将android:windowBackground 修改为蓝色;下面来看看效果;
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light">
<!--在这里重写android:windowBackground 将它的颜色改为蓝色-->
<item name="android:windowBackground">@color/assist_blue_down</item>
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimarydark</item>
<item name="colorAccent">@color/coloraccent</item>
<!--去掉系统默认的标题栏-->
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<!-- 设置activity切换动画 -->
<item name="android:windowAnimationStyle">@style/activityAnimation</item>
</style>
我们修改成蓝色后,注意到没?启动时候,这里使我们自己设置的蓝色了吧?那是不是就可以在这类放一张启动图片了?
这里放一张启动图片(广告图)后,那启动的时候,就先出来的是那张启动图片(广告图)了;
来看看用图片的效果
我们来放这张图片,来看看效果
总结(修改全局的主题)
这样直接修改全局的主题会有个不好的问题,就是会造成APP的每一个页面都会有这样一个背景图,就会牵扯到布局优化的过度渲染了,如果不了解布局优化的,请移步到我的另一篇博客中:
Android UI绘制优化及建议
修改局部的主题
我们这里新加一个主题;将背景设置成广告的图片,也就是去掉这个自带的android:windowBackground:@null
<style name="AppTheme.Launcher1">
<item name="android:windowBackground">@drawable/bg</item>
</style>
然后在这个LAUNCHER页面中去设置这个独立的主题Launcher1
<activity
android:theme="@style/AppTheme.Launcher1"
android:name=".activity.SplashActivity"
android:screenOrientation="portrait"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
在代码中再设置主题,效果和上面一样,这里我就不放gif图片了
public class SplashActivity extends BaseActivity {
private static final String TAG = "david";
@Override
protected void onCreate(Bundle savedInstanceState) {
// setTheme(R.style.AppTheme);
super.onCreate(savedInstanceState);
setTheme(R.style.AppTheme_Launcher1);
}
}
真正的优化
尽可能的去减少Activity、Application中onCreate中的耗时代码;
我们来分析Application中onCreate方法的耗时
启动时间:Debug.startMethodTracing(file.getAbsolutePath());
结束时间:Debug.stopMethodTracing();
用这两个方法的调用来,记录这个时间,生成.trace文件,注意要开好文件存储权限;
直接冷启动运行APP,生成文件,然后我们把文件导出来
然后把这个文件拖入到我们的AS里面;
结合我们这个Application中的onCreate来看上面的图
可以发现第一行自己调用的方法吧,然后对应段落下出现了很多各种段落,表示的是方法中调用的其方法,第一行可以看得出这个对应方法以及内部调用后的所需要时间,也就是每个方法的执行耗费的时间;
鼠标放到上面,可以有这个方法执行所耗费的时间注意看我鼠标那,框中最下面显示:6.62ms (表示这个方法执行了6.62毫秒)
public class App extends Application {
private static final String TAG = "jett";
public static List<Activity> activities = new LinkedList<Activity>();
@Override
public void onCreate() {
super.onCreate();
File file = new File(Environment.getExternalStorageDirectory(), "app1.trace");
Log.i(TAG, "onCreate: " + file.getAbsolutePath());
//把分析结果存在一个文件
Debug.startMethodTracing(file.getAbsolutePath());
//对全局属性赋值
mContext = getApplicationContext();
mMainThread = Thread.currentThread();
mMainThreadId = android.os.Process.myTid();
mMainLooper = getMainLooper();
mHandler = new Handler();
//因为LQRUIKit中已经对ImageLoader进行过初始化了
initImageLoader(getApplicationContext());
initNim();
initImagePicker();
initOkHttp();
NIMClient.init(this, loginInfo(), options());
Debug.stopMethodTracing();
}
private void initOkHttp() {
}
}
如果不喜欢看图的,也可以来看看这个
上图中,第三列%:表示这段总耗时,每个方法对应消耗的百分比;
注意看:initImageLoader、initNim方法耗时占比比较大吧?
我们就需要解决掉这两个方法的耗时,这两个方法处理的价值是最大的,其余的想处理的也可以去处理,看个人;
优化
这类我们将耗时的、对异步要求不高、调用的方法中没去创建handler 没操作UI 的初始化方法,放到了子线程中去调用;
并将可以做懒加载的方法,注释掉,让需要用的地方去做懒加载;
public class App extends Application {
private static final String TAG = "jett";
public static List<Activity> activities = new LinkedList<Activity>();
@Override
public void onCreate() {
super.onCreate();
File file = new File(Environment.getExternalStorageDirectory(), "app1.trace");
Log.i(TAG, "onCreate: " + file.getAbsolutePath());
//把分析结果存在一个文件
Debug.startMethodTracing(file.getAbsolutePath());
//对全局属性赋值
mContext = getApplicationContext();
mMainThread = Thread.currentThread();
mMainThreadId = android.os.Process.myTid();
mMainLooper = getMainLooper();
mHandler = new Handler();
//因为LQRUIKit中已经对ImageLoader进行过初始化了
//
new Thread(){
@Override
public void run() {
initImageLoader(getApplicationContext());
//如果要用线程来节约了这些初始化的时间
//1.里面的API不能去创建handler
//2.不能有UI操作
//3.对异步要求不高
initNim();
initImagePicker();
initOkHttp();//可以懒加载
}
}.start();
NIMClient.init(this, loginInfo(), options());
Debug.stopMethodTracing();
}
}
来看看这个优化后的时间
是不是减少了很多?这样就会让我们APP在启动的时间,减少耗时启动了;
真正优化的总结
优化方案:
1.开线程 调用的方法中没去创建handler 没操作UI 对异步要求不高;
2.懒加载 用到的时候再初始化,如网络,数据库操作;
注意:如果有些需要马上要用到的一些对象和框架,尽量去做懒加载,防止异步加载的对象和框架还没加载完成,在页面中马上使用,造成空指针或者一些异常
还有一些耗时的,可以不放在Application里面,结合懒加载可以在启动页LAUNCHER中,设置主题背景,然后在启动页中启动定时广告,相信大部分框架和代码在这个广告三秒的时间内能初始化完成了。还可以在这三秒中调用下载下一次启动时的图片广告信息等等
感谢收看到最后的童鞋