欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android-APP启动优化

程序员文章站 2022-05-16 20:24:51
...


黑白屏问题优化
黑白屏在商业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();
    }
}

这一块白屏是不是很难看?
注: 这个不是微信,这个是我在码云上面下载的一个模仿微信的项目哦;
Android-APP启动优化
以前都会觉得是个很难看的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>

我们修改成蓝色后,注意到没?启动时候,这里使我们自己设置的蓝色了吧?那是不是就可以在这类放一张启动图片了?
这里放一张启动图片(广告图)后,那启动的时候,就先出来的是那张启动图片(广告图)了;
Android-APP启动优化
来看看用图片的效果
我们来放这张图片,来看看效果Android-APP启动优化
Android-APP启动优化

总结(修改全局的主题)

这样直接修改全局的主题会有个不好的问题,就是会造成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,生成文件,然后我们把文件导出来
Android-APP启动优化
然后把这个文件拖入到我们的AS里面;
Android-APP启动优化

结合我们这个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() {

    }
}

如果不喜欢看图的,也可以来看看这个
Android-APP启动优化
上图中,第三列%:表示这段总耗时,每个方法对应消耗的百分比;
注意看: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();
    }
}

来看看这个优化后的时间
Android-APP启动优化
Android-APP启动优化
是不是减少了很多?这样就会让我们APP在启动的时间,减少耗时启动了;

真正优化的总结

优化方案:
1.开线程 调用的方法中没去创建handler 没操作UI 对异步要求不高;
2.懒加载 用到的时候再初始化,如网络,数据库操作;

注意:如果有些需要马上要用到的一些对象和框架,尽量去做懒加载,防止异步加载的对象和框架还没加载完成,在页面中马上使用,造成空指针或者一些异常
还有一些耗时的,可以不放在Application里面,结合懒加载可以在启动页LAUNCHER中,设置主题背景,然后在启动页中启动定时广告,相信大部分框架和代码在这个广告三秒的时间内能初始化完成了。还可以在这三秒中调用下载下一次启动时的图片广告信息等等

感谢收看到最后的童鞋