总结
通过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的,也需要根据情况做处理。