App启动时黑白屏优化
黑白屏问题是app需要重点优化点之一,我以前都是遇到这种比较典型的问题直接上网查找相关的解决方案,筛选直接用,这样的缺点是,只知其表,不知其里,感觉自己这块懂了,但是和人实际表述的时候却说的很片面。细致梳理一下,让自己认知更深刻一下。如果有理解不对的地方,请多多指点。在此先谢过!!
1 、app的启动流程图:
小结:从图中可以看出app启动分为俩个阶段,一个是系统进程层,一个是application进程层。修改系统层需要root权限,所以真正的优化其启动速速是在application进程中。这里只分析application进程。这个流程图就是冷启动的过程。
所谓冷启动:冷启动是指进程未被创建的时候,用户launcher点击图标启动app的过程。
热启动:用户点击back键,退到手机应用图标界面,这时候进程没有被杀死,在点击应用的图标启动应用。
分析一:在此过程中,系统要为app创建一个进程,并且这个过程还包含Activity的绘制过程,这些都是比较耗时的。针对以上因素,所以Android系统框架设计了一个startWindow窗口,在app的window窗口绘制完毕之前,系统会先让startWinow窗口显示,直到activity的window窗口初始化完毕。我们所说的黑白屏就是startWindow窗口,黑或白是我们窗口的背景颜色,而背景颜色是由主题的背景颜色决定。只要我们解决这个主题背景色的问题,这个问题也就解决了。
分析二:在大中型项目中,一般都是在application中初始化组件和集成的第三方sdk,其在初始化的时候会消耗大量的时间。这就导致我们app启动比较缓慢,造成黑白屏时间过长,用户体验差的效果。
2、原因我们已经找到,下面来分析一下解决方案:
从网上各种针对此问题的文章做了总结归纳:解决方案有以下几种:
①自定义一个主题,把主题窗口背景色设置为透明,在application中设置这个主题
②修改我们的主题背景图片,图片设置为我们app的logo,在application中引用这个主题
③优化application初始化所需要的时间(一般都是开启子线程,常用的是IntentService)
3、具体实施步骤
①设置透明主题:代码如下
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
...
<item name="android:windowIsTranslucent">true</item>
</style>
此种方案特点:就是当我们点击应用图标的时候,会感觉反应不那么快,不熟悉的人以为自己没有打开成功,会连续点击。如果启动时间过长,那么用户体验比较差。
②给自定义主题设置背景图片,图片是我们的logo图片,现在市场很多app都是应用此方法。代码如下
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/splash</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
注意点:在我们的splash页面onCreate方法中要添加下面一行代码:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
这行代码的作用:不显示系统标题栏,保证我们启动的windowbackground和我们布局文件显示的大小一样大,防止图片错位。
③优化我们application onCreate方法中耗时操作,常借助IntentService
IntentService:其本质是一个特殊的service,它是一个抽象类,并且是继承Service。它可以在后台执行耗时的异步任务,当任务完成后会自动停止,优先级比较高,不容易被杀死(原因:继承service),它内部是使用HandlerThread 和handler实现异步操作的,创建IntentService时只需要实现onHandlerIntent和构造方法即可。系统执行onHandlerIntent方法时候会帮我们创建一个子线程,并且在任务执行完毕后,自动调用stopService方法,停止服务,不需要我们终止。优化代码如下:
创建IntentService,代码如下:
import android.app.IntentService;
import android.content.Intent;
import android.content.Context;
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//这里进行耗时操作
}
public static void init(Context context) {
Intent intent = new Intent(context, MyIntentService.class);
context.startService(intent);
}
}
在清单文件中进行注册:
<service
android:name=".ui.MyIntentService"
android:exported="false"></service>
如果想省去注册这步,可以直接借助Studio,File ->New ->Service ->IntentServic,直接创建即可。
在application中代码如下
MyIntentService.init(this);
把耗时操作直接放在,intentService中进行处理即可。
在实际应用中,这三种方案我们可以混搭使用,让其优化效果更加完美。