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绘制优化及建议

修改局部的主题

我们这里新加一个主题;将背景设置成广告的图片

       <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 = "kaizi";
    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 = "kaizi";
    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中,设置主题背景,然后在启动页中启动定时广告,相信大部分框架和代码在这个广告三秒的时间内能初始化完成了。还可以在这三秒中调用下载下一次启动时的图片广告信息等等

感谢收看到最后的童鞋

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值