启动速度优化

2021-12-09  本文已影响0人  涛涛123759

Android知识总结

一、启动流程

Activity启动流程

①、点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;

②、system_server进程接收到请求后,向zygote进程发送创建进程的请求;

③、Zygote进程fork出新的子进程,即App进程;

④、App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
⑤、system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;

⑥、App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

⑦、主线程在收到Message后,通过反射机制创建目标Activity,并回调Activity.onCreate()等方法。

⑧、到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。

二、启动状态

应用有三种启动状态,每种状态都会影响应用向用户显示所需的时间:冷启动温启动热启动。在冷启动中,应用从头开始启动。在另外两种状态中,系统需要将后台运行的应用带入前台。建议始终在假定冷启动的基础上进行优化。这样做也可以提升温启动和热启动的性能。

  • 用户在退出应用后又重新启动应用。进程可能未被销毁,继续运行,但应用需要执行 onCreate() 从头开始重新创建 Activity。

  • 系统将应用从内存中释放,然后用户又重新启动它。进程和 Activity 需要重启,但传递到 onCreate() 的已保存的实例savedInstanceState对于完成此任务有一定助益。

三、启动耗时统计

3.1、系统日志统计

在 Android 4.4(API 级别 19)及更高版本中,logcat 包含一个输出行,其中包含名为 Displayed 的值。此值代表从启动进程到在屏幕上完成对应 Activity 的绘制所用的时间。

3.2、adb命令统计

adb shell
am start -S -R -W [包名]/[启动的Activity全类名、或在一个包下直接 .Activity]

开发者一般只要关心TotalTime即可,这个时间才是自己应用真正启动的耗时。

3.3、启动耗时统计

adb 命令启动应用,一般会输入三个值:ThisTimeTotalTimeWaitTime

四、CPU Profile

public class MyApplication extends Application {
    public MyApplication() {
    Debug.startMethodTracing("enjoy");
}
//.....
}
public class MainActivity extends AppCompatActivity {
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        Debug.stopMethodTracing();
    }
//.......
}

运行App,则会在sdcard中生成一个enjoy.trace文件(需要sdcard读写权限)。将手机中的trace文件保存至电脑,随后拖入Android Studio即可。

三、StrictMode

StrictMode是一个开发人员工具,它可以检测出我们可能无意中做的事情,并将它们提请我们注意,以便我们能够修复它们。

StrictMode最常用于捕获应用程序主线程上的意外磁盘或网络访问。帮助我们让磁盘和网络操作远离主线程,可以使应用程序更加平滑、响应更快。

public class MyApplication extends Application {

    public MyApplication() {

    }

    @Override
    public void onCreate() {
        if (BuildConfig.DEBUG) {
            //线程检测策略
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()   //读、写操作
                    .detectDiskWrites()
                    .detectNetwork()   // or .detectAll() for all detectable problems
                    .penaltyLog()
                    .penaltyDeath()
                    .build());
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                    .detectLeakedSqlLiteObjects()   //Sqlite对象泄露
                    .detectLeakedClosableObjects()  //未关闭的Closable对象泄露
                    .penaltyLog()  //违规打印日志
                    .penaltyDeath() //违规崩溃
                    .build());
        }

        super.onCreate();
    }
}

六、冷启动白屏问题

当系统加载并启动 App 时,需要耗费相应的时间,这样会造成用户会感觉到当点击 App 图标时会有 “延迟” 现象,为了解决这一问题,Google 的做法是在 App 创建的过程中,先展示一个空白页面,让用户体会到点击图标之后立马就有响应。

如果你的application或activity启动的过程太慢,导致系统的BackgroundWindow没有及时被替换,就会出现启动时白屏或黑屏的情况(取决于Theme主题是Dark还是Light)。

消除启动时的黑/白屏问题,大部分App都采用自己在Theme中设置背景图的方式来解决。

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- 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>
    </style>

    <style name="AppTheme.Launcher">
        <item name="android:windowBackground">@drawable/bg</item>
        <item name="android:windowFullscreen">true</item>
    </style>
</resources>
<activity android:name=".MainActivity" android:theme="@style/AppTheme.Launcher">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

然后在Activity的onCreate方法,把Activity设置回原来的主题。

@Override
protected void onCreate(Bundle savedInstanceState) {
    //替换为原来的主题,在onCreate之前调用
    setTheme(R.style.AppTheme);
    super.onCreate(savedInstanceState);
}

七、总结

启动速度优化也会涉及到布局优化与卡顿优化,包括内存抖动等问题。优化是一条持续的道路,很多时候我们会发现通过各种检测手段花费了大量的精力去对代码进行修改得到的优化效果可能并不理想。因为优化就是一点一滴积累下来的,我们平时在编码的过程中就需要多注意自己的代码性能。

可能实际过程中优化并不会很顺利,不同的设备上可能表现不一样。我们只能结合对业务、对自己代码的了解去不断去实践。

上一篇 下一篇

猜你喜欢

热点阅读