安卓启动速度优化——延迟启动Provider

613 阅读1分钟

总结

通过appComponentFactory拦截所有Provider启动,然后用DelayContentProviderProxy替换,应用页面显示后,再去启动所有Provider,从而实现延迟启动Provider。

优化前在小米9上启动时间为7984毫秒。优化后为841毫秒。应用中有10个Provider。

最开始优化时,都在找哪有IO操作,全换成协程IO,优化后效果不明显,基本都ANR。直到延迟启动Provider后,才解决问题。

TinkerApp cost 841
createAndActivateRealContentProvider androidx.startup.InitializationProvider, cost 9
createAndActivateRealContentProvider io.sentry.android.core.SentryPerformanceProvider, cost 3
createAndActivateRealContentProvider com.huawei.hms.mlsdk.common.provider.MLInitializerProvider, cost 2
createAndActivateRealContentProvider com.xxx.debug.AopProvider, cost 0
createAndActivateRealContentProvider com.xxx.OcrFileProvider, cost 6
createAndActivateRealContentProvider com.xxx.ApkFileProvider, cost 6
createAndActivateRealContentProvider com.yanzhenjie.album.provider.CameraFileProvider, cost 3
createAndActivateRealContentProvider com.huawei.agconnect.core.provider.AGConnectInitializeProvider, cost 3
createAndActivateRealContentProvider io.sentry.android.core.SentryInitProvider, cost 89
createAndActivateRealContentProvider com.liulishuo.okdownload.OkDownloadProvider, cost 0

用法

依赖地址:jitpack

manifest中使用DelayProviderFactory

    <application
        android:name=".App"
        android:appComponentFactory="com.donald.dps.lib.DelayProviderFactory"

可App中设置启用/禁用delayProvider,来测试加速效果,默认启用。 可设置取消延迟启动的Provider,如果没有特别要求,不需要在App中做任何调用。

public class App extends Application {
    @Override
    protected void attachBaseContext(Context base) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
//            DelayProviderHelper.delayProvider(false);//禁用delayProvider
            DelayProviderHelper.cancelDelayProvider(MyDerectContentProvider.class.getName());
        }
        super.attachBaseContext(base);
    }
}

在应用页面显示完成后,开始enableDelayProvider。 建议在BaseActivity的onResume中调用,以适配多种页面,比如应用启动后,可能进入:欢迎页,登录页,主页,推送消息详情页,等等。

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        assert(MyDerectContentProvider.started)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            if (!DelayProviderFactory.derectProvider) {
                assert(!MyDelayContentProvider.started)
                DelayProviderHelper.enableDelayProvider(null)
                window.decorView.postDelayed({
                    assert(MyDelayContentProvider.started)//异步启动Provider,只能延迟检查
                }, MyDelayContentProvider.delayMS + 300)
            }
        } else {
            assert(MyDelayContentProvider.started)
        }
    }
}

其它说明

  • 如果有提供给外部调用的Provider,就加入取消延迟启动(DelayProviderHelper.cancelDelayProvider)列表。
  • 如果有多个android:process的,也需要根据情况做处理。