Jetpack ---- App Startup源码解析

本文详细介绍了Android的Jetpack库App Startup的使用和原理,包括如何解决SDK初始化问题、如何实现懒加载、源码解析以及优缺点分析。通过App Startup,可以更高效地管理应用启动时的初始化操作,减少ContentProvider的性能损耗,同时简化代码维护。
摘要由CSDN通过智能技术生成

1. 解决的问题

一般需要初始化的sdk都会对外提供一个初始化方法供外界调用,如:

public class App extends Application {
   

    @Override
    public void onCreate() {
   
        super.onCreate();
        Sdk1.init(this);
    }
}

对调用者很不友好。另一种做法是使用ContentProvider初始化,如下:

public class Sdk1InitializeProvider extends ContentProvider {
   
    @Override
    public boolean onCreate() {
   
        Sdk1.init(getContext());
        return true;
    }
	...
}

然后在AndroidManifest.xml文件中注册这个privoder,如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.zhengzhengxiaogege.sdk1">
    <application>
        <provider
            android:authorities="${applicationId}.init-provider"
            android:name=".Sdk1InitializeProvider"
            android:exported="false"/>
    </application>
</manifest>

authorities在这里并没有固定的要求,填写什么值都是可以的,但必须保证这个值在整个手机上是唯一的,所以通常会使用 ${applicationId} 作为前缀,以防止和其他应用程序冲突。

这样初始化的逻辑就由Sdk开发者在内部完成了。

那么,自定义的这个Sdk1InitializeProvider 它会在什么时候执行呢?我们来看一下这张流程图:
在这里插入图片描述
可以看到,一个应用程序的执行顺序是这个样子的。首先调用Application的attachBaseContext()方法,然后调用ContentProvider的onCreate()方法,接下来调用Application的onCreate()方法

有没有觉得ContentProvider的onCreate()方法中进行初始化这种设计方式很巧妙?它可以将库的用法进一步简化,不需要你主动去调用初始化接口,而是将这个工作在背后悄悄自动完成了。

那么有哪些库使用了这种设计方式呢?这个真的有很多了,比如说Facebook的库,Firebase的库,还有我们所熟知的WorkManager,Lifecycles等等。这些库都没有提供一个像LitePal那样的初始化接口,其实就是使用了上述的技巧。

看上去如此巧妙的技术方案,那么它有没有什么缺点呢?

有,缺点就是,ContentProvider会增加许多额外的耗时。

毕竟ContentProvider是Android四大组件之一,这个组件相对来说是比较重量级的。也就是说,本来我的初始化操作可能是一个非常轻量级的操作,依赖于ContentProvider之后就变成了一个重量级的操作了。

关于ContentProvider的耗时,Google官方也有给出一个测试结果:
在这里插入图片描述
这是在一台搭载Android 10系统的Pixel2手机上测试的情况。可以看到,一个空的ContentProvider大约会占用2ms的耗时,随着ContentProvider的增加,耗时也会跟着一起增加。如果你的应用程序中使用了50个ContentProvider,那么将会占用接近20ms的耗时。

注意这还只是空ContentProvider的耗时,并没有算上你在ContentProvider中执行逻辑的耗时。

这个测试结果告诉我们,虽然刚才所介绍的使用ContentProvider来进行初始化的设计方式很巧妙,但是如果每个第三方库都自己创建了一个ContentProvider,那么最终我们App的启动速度就会受到比较大的影响。

但是,如果一个app依赖了很多需要初始化的sdk,如果都放在一个ContentProvider中会导致此ContentProvider代码数量增加。而且每增加一个需要初始化的sdk都要对该ContentProvider文件做改动,不方便合作开发。而如果每个sdk都采用同样的方式将会带来性能问题。App Startup library可以有效解决这个问题。

2. 使用App StartUp

(1) 添加依赖

在App模块的build.gradle文件中添加依赖:

dependencies {
   
    implementation "androidx.startup:startup-runtime:1.0.0"
}

(2) 实现Initializer< T >接口

app通过Initializer< T >接口接入App Startup,需要实现两个方法

public interface Initializer<T> {
   

  @NonNull
  T create(@NonNull Context context);

  @NonNull
  List<Class<? extends Initializer<?>>> dependencies();
}

例如有一个Sdk1如下:

public class Sdk1 {
   
  private static final String TAG = "Sdk1";

  private static Context sApplicationContext;

  private static volatile Sdk1 sInstance;

  public static void init(Context applicationContext){
   
      sApplicationContext = applicationContext;
      Log.e(TAG, "Sdk1 is initialized");
  }

  public static Sdk1 getInstance(){
   
      if (sInstance == null) {
   
          synchronized (Sdk1.class){
   
              if (sInstance == null) {
   
                  sInstance = new Sdk1();
              }
          }
      }
      return sInstance;
  }

  private Sdk1(){
   
  }

  public void printApplicationName(){
   
      Log.e(TAG, sApplicationContext.getPackageName());
  }
}

sdk1对外提供Sdk1类,包含初始化方法init(Context),实例获取方法getInstance()和对外的服务方法printApplicationName()。为了使用App Startup,需要提供一个初始化器如下:

public class
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值