Android 12 源码分析 —— 应用层 三(SystemUIFactory及其Dependency解析)

Android 12 源码分析 ------ 应用层 三(SystemUIFactory及其Dependency解析)

在上一篇文章中,介绍了SystemUI的启动流程,并且简单提及了Dagger2用来管理各个SystemUI中要用的依赖。而这部分代码就在:mContextAvailableCallback.onContextAvailable(this);流程中。而这部分流程我们只是一笔带过,并没有仔细分析。

接下来将会从这个调用开始,介绍SystemUI中Component,subcomponent的初始化,并理解应该怎么使用这些Component。

本文会先以一个例子,简单引入Dagger2中对各个注解的生成模板,然后在介绍SystemUI中重要component和subcomponent的创建过程,最后过渡到一个关键的类Dependency

注意:此处之所以另起一个例子来说明Dagger2的生成模板,完全是因为Dagger2对SystemUI的生成代码太多,导致不太好列成文档

理解Dagger2的模板

为了能够更好理解Dagger2的生成代码的模板,我们按照如下的例子进行编写,然后查看生成的类.

将下面的代码放入一个DemoComponent.java的文件中

java 复制代码
//最顶层的Component,其有两个模块,分别为:
//      DemoSubComponent1.DemoModule1
//      DemoSubComponent2.DemoModule2
//最顶层Component,提供两个接口,用于得到SubComponent的Factory和Builder类
@Component(modules = {DemoSubComponent1.DemoModule1.class,
                        DemoSubComponent2.DemoModule2.class})
public interface DemoComponent {
    DemoSubComponent1.Factory getSubComponent1Factory();
    DemoSubComponent2.Builder getSubComponent2Builder();
}

//SubComponent1,提供如下两个功能
//      1. 获得DemoAClass对象
//      2. 向DemoInject对象中,注入需要的对象
@SysUISingleton
@Subcomponent
interface DemoSubComponent1{

    @Subcomponent.Factory
    interface Factory {
        DemoSubComponent1 create();
    }

    DemoAClass getAClass();

    void inject(DemoInject inject);

    //SubComponent1隶属于的模块
    //指定了DemoInterface 和DemoBinds之间的关系,当需要DemoInterface的时候,
    //  Dagger2会创建对应的DemoBinds对象
    @Module(subcomponents = DemoSubComponent1.class)
    abstract class DemoModule1{
        @Binds
        abstract DemoInterface getInterface(DemoBinds bindings);
    }
}

//SubComponent2,提供一个功能
//    1. 获取DemoBClass对象
@Subcomponent
interface DemoSubComponent2{

    //为了和SubComponent1作区分,这里使用了Builder类来创建SubComponent2
    @Subcomponent.Builder
    interface Builder {
        DemoSubComponent2 build();
    }


    DemoBClass getBClass();

    //SubComponent2隶属的模块,该模块还提供了一个@Provides
    @Module(subcomponents = DemoSubComponent2.class)
    class DemoModule2{

        //当需要DemoProvider对象的时候,就会调用此方法
        @Provides
        DemoProvider getProvider(){
            return new DemoProvider();
        }
    }
}

//用于演示@Binds
interface DemoInterface{
    void test();
}

//用于演示@Binds
class DemoBinds implements DemoInterface{

    @Inject
    DemoBinds(){

    }

    @Override
    public void test() {

    }
}

//用于演示@Provides
class DemoProvider{

}

//用于演示,inject函数
class DemoInject{
    @Inject
    DemoAClass a;
}

//用于演示,生命周期
@SysUISingleton
class DemoAClass{
    @Inject
    public DemoAClass(){

    }
}

//用于演示返回的对象
class DemoBClass{
    @Inject
    public DemoBClass(){

    }
}

有了上面所画的图,接下来查看,Dagger2根据图生成的文件,生成的文件有:

  1. DaggerDemoComponent.java
  2. DemoAClass_Factory.java
  3. DemoBClass_Factory.java
  4. DemoBinds_Factory.java
  5. DemoInject_MembersInjector.java
  6. DemoSubComponent2_DemoModule2_GetProviderFactory.java
  7. DemoSubComponent2_DemoModule2_Proxy.java

接下来我们挨个查看生成的7个文件,分别是什么内容,DaggerDemoComponent.java中会使用剩下的6个类。因此,我们先看剩下的6个类,最后再查看DaggerDemoFactory.java

DemoAClass_Factory,DemoBClass_Factory,DemoBinds_Factory

DemoAClass_Factory的源码如下:

java 复制代码
//对于任何类来讲,只要其构造函数带有@Inject,则Dagger2都会创建一个对应的工厂类,
//叫做:XXX_Factory,它实现了Factory<T>接口
//欲使用这个工厂类,则调用create()方法,得到这个工厂类的实例,工厂类的实例永远只有一个
//欲使用这个工厂类产生的对象,则调用newInstance()方法,得到工厂类的产生对象,
//工厂类产生的对象可以有多个
public final class DemoAClass_Factory implements Factory<DemoAClass> {
  @Override
  public DemoAClass get() {
    return newInstance();
  }

  public static DemoAClass_Factory create() {
    return InstanceHolder.INSTANCE;
  }

  public static DemoAClass newInstance() {
    return new DemoAClass();
  }

  //用于缓存工厂类实例
  private static final class InstanceHolder {
    private static final DemoAClass_Factory INSTANCE = new DemoAClass_Factory();
  }
}

DemoBClass_Factory,DemoBinds_Factory同DemoAClass_Factory一模一样,不再啰嗦。

DemoInject_MembersInjector

DemoInject_MembersInjector用于辅助成员的注入,因为在DemoInject类中如下的代码

java 复制代码
class DemoInject{
    @Inject
    DemoAClass a;
}

整个辅助类源码如下:

java 复制代码
//每一个辅助注入的类,都是MembersInjector<T>的具体实现
//在实现中,对要注入的成员,使用Provider<T>表示,抽象为:T的提供者。它会在辅助类创建的时候被
//初始化好
//        对被注入的类,使用instance表示
//同工厂类一样,辅助注入类的实例化,也是通过create()方法进行
//同工厂类不一样的是,每次create,都会创建不同的辅助注入对象
//注入方式,则直接调用injectMembers()函数进行
public final class DemoInject_MembersInjector implements MembersInjector<DemoInject> {
  private final Provider<DemoAClass> aProvider;

  public DemoInject_MembersInjector(Provider<DemoAClass> aProvider) {
    this.aProvider = aProvider;
  }

  public static MembersInjector<DemoInject> create(Provider<DemoAClass> aProvider) {
    return new DemoInject_MembersInjector(aProvider);
  }

  @Override
  public void injectMembers(DemoInject instance) {
    injectA(instance, aProvider.get());
  }

  @InjectedFieldSignature("com.android.systemui.dagger.DemoInject.a")
  public static void injectA(Object instance, Object a) {
    ((DemoInject) instance).a = (DemoAClass) a;
  }
}

上面的辅助注入类也很简单,接着往下看

DemoSubComponent2_DemoModule2_GetProviderFactory

DemoSubComponent2_DemoModule2_GetProviderFactory类表示的是对@Provides的实现工厂类,源码如下:

java 复制代码
//对于任何一个被@Provides标记的函数,Dagger2都会创建一个提供者工厂类,它实现了Factory<T>
//同DemoAClass工厂类一样,它也会有一个create()方法,用于实例化提供者工厂类
//不同之处在于,每次调用都会创建一个新的提供者工厂类

//只有需要提供者工厂类,生产提供者时,才会调用get()方法,用于返回生产出来的对象。

public final class DemoSubComponent2_DemoModule2_GetProviderFactory implements Factory<DemoProvider> {
  private final DemoSubComponent2.DemoModule2 module;

  public DemoSubComponent2_DemoModule2_GetProviderFactory(DemoSubComponent2.DemoModule2 module) {
    this.module = module;
  }

  @Override
  public DemoProvider get() {
    return getProvider(module);
  }

  public static DemoSubComponent2_DemoModule2_GetProviderFactory create(
      DemoSubComponent2.DemoModule2 module) {
    return new DemoSubComponent2_DemoModule2_GetProviderFactory(module);
  }

  public static DemoProvider getProvider(DemoSubComponent2.DemoModule2 instance) {
    return Preconditions.checkNotNullFromProvides(instance.getProvider());
  }
}

上面的代码,依然很简单,不再啰嗦

DemoSubComponent2_DemoModule2_Proxy

DemoSubComponent2_DemoModule2_Proxy是对抽象模块的表示,源码如下:

java 复制代码
public final class DemoSubComponent2_DemoModule2_Proxy {
  private DemoSubComponent2_DemoModule2_Proxy() {
  }

  public static DemoSubComponent2.DemoModule2 newInstance() {
    return new DemoSubComponent2.DemoModule2();
  }
}

在DemoModule2中,没有任何需要实现的地方,且@Binds已经语义足够明显,所以上面生成的类,没有任何过多的地方。较简单

接下来,就是看看DaggerDemoComponent如何使用上面创建的类来处理他们之间的依赖关系

DaggerDemoComponent

DaggerDemoComponent是整个依赖注入的入口,其源码如下:

java 复制代码
//实现我们的DemoComponent接口,其命名为DaggerAAA_BBB。其中下划线后面的名字,为内部类的名字
public final class DaggerDemoComponent implements DemoComponent {
  private DaggerDemoComponent() {

  }

  //builder()方法和create()方法,都是为了创建DaggerDemoComponent的实例
  public static Builder builder() {
    return new Builder();
  }

  public static DemoComponent create() {
    //委托给Builder类创建
    return new Builder().build();
  }

  //返回subcomponent1的Factory类,用于创建subcomponent1
  @Override
  public DemoSubComponent1.Factory getSubComponent1Factory() {
    //见后文
    return new DemoSubComponent1Factory();
  }

  //返回subcomponent2的Bulder类,用于创建subcomponent2
  @Override
  public DemoSubComponent2.Builder getSubComponent2Builder() {
    return new DemoSubComponent2Builder();
  }

  //用于创建DaggerDemoComponent,在这个类中,只是简单的new了一个DaggerDemoComponent即可
  public static final class Builder {
    private Builder() {
    }

    
    @Deprecated
    public Builder demoModule2(DemoSubComponent2.DemoModule2 demoModule2) {
      Preconditions.checkNotNull(demoModule2);
      return this;
    }

    public DemoComponent build() {
      return new DaggerDemoComponent();
    }
  }

  //实现DemoSubComponent1的Factory接口,该接口提供create()方法来创建对应的实例
  private final class DemoSubComponent1Factory implements DemoSubComponent1.Factory {
    @Override
    public DemoSubComponent1 create() {
      //创建DemoSubComponent1的实例对象,并返回
      return new DemoSubComponent1Impl();
    }
  }

  //subcomponet1的具体实现
  private final class DemoSubComponent1Impl implements DemoSubComponent1 {
    private Provider<DemoAClass> demoAClassProvider;

    private DemoSubComponent1Impl() {
      
      initialize();
    }
    //辅助构造函数,对DemoAClass的提供者,进行初始化

    //因为我们将DemoAClass的生命周期和DemoSubComponent1的生命周期,都标记为
    //@SysUISingleton
    //所以他们同生同死,为了达到这个效果,需要在subcomponent1中持有对DemoAClass的提供者,
    //而不是每次重新创建(对比下面的getBClass()函数)
    //这样,在需要DemoAClass的地方(如getAClass()函数),就直接让提供者来提供,而提供者保证了
    //每次都提供同一个对象

    //DemoAClass的提供者,我们首先想到的就是,前面介绍过的DemoAClass_Factory工厂类,
    //调用其newInstance()
    //就会创建一个DemoAClass对象。但是它并不能保证每次提供同一个对象,因此再次对
    //DemoAClass_Factory进行封装
    //这个封装就是DoubleCheck对象,它保证了每次提供同一个对象,同时也保证了线程安全
    //DoubleCheck最终也会使用DemoAClass_Factory类来实例化DemoAClass对象
    @SuppressWarnings("unchecked")
    private void initialize() {
      this.demoAClassProvider = DoubleCheck.provider(DemoAClass_Factory.create());
    }

    //调用DemoAClass的提供者,让其提供同一个对象
    @Override
    public DemoAClass getAClass() {
      return demoAClassProvider.get();
    }

    //向DemoInject中注入需要的成员
    @Override
    public void inject(DemoInject inject) {
      injectDemoInject(inject);
    }

    //调用对应的辅助注入类,注入需要的成员
    private DemoInject injectDemoInject(DemoInject instance) {
      DemoInject_MembersInjector.injectA(instance, demoAClassProvider.get());
      return instance;
    }
  }

  //subcomponnet2的Builder接口实现
  private final class DemoSubComponent2Builder implements DemoSubComponent2.Builder {
    @Override
    public DemoSubComponent2 build() {
      //创建subcomponent2对象,并直接返回
      return new DemoSubComponent2Impl();
    }
  }

  //subcomponent2的具体实现类
  private final class DemoSubComponent2Impl implements DemoSubComponent2 {

    //因为DemoSubComponent2和DemoBClass并不是同一生命周期,所以,每次都创建一个新的
    //DemoBClass对象返回
    //因此,也就不需要相应的提供者类,也就不需要相应的对提供者类进行初始化    
    private DemoSubComponent2Impl() {

    }

    @Override
    public DemoBClass getBClass() {
      return new DemoBClass();
    }
  }
}

在Component中完成了如下的工作:

  1. 实现了component,subcomponent,以及他们对应的Builder, Factory类,subcomponent是component的内部类
  2. 实现对应的接口方法,这些方法,会委托给其他的xxx_Factory,xxxx_MembersInjector辅助类来完成
  3. 被委托的xxx_Factory工厂类,xxx_MembersInjector辅助类,都会被正确的初始化

至此,我们对Dagger2生成的模板有了一个整体把握,并对其中的实现细节,做了一些注释说明。

接下来我们继续看看SystemUI中的重要组件的创建过程

SystemUI 创建Dagger2依赖的起点

第一篇文章,我们一笔带过了SystemUIApplication.onCreate()中的mContextAvailableCallback.onContextAvailable(this).

这就是Dagger2创建依赖的起点,mContextAvailableCallback的赋值,在SystemUIAppComponentFactory.java中。

如下:

java 复制代码
@NonNull
@Override
//此函数在创建SystemUIApplication之前调用
public Application instantiateApplicationCompat(
        @NonNull ClassLoader cl, @NonNull String className)
        throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    //调用父类方法,创建Application,此处的app实例为SystemUIApplication
    Application app = super.instantiateApplicationCompat(cl, className);
    if (app instanceof ContextInitializer) {
        //给SystemUIApplication的mContextAvailableCallback赋值
        ((ContextInitializer) app).setContextAvailableCallback(
                context -> {
                    //SystemUIApplication的onCreate处开始调用

                    //1. 首先创建SystemUIFactory(SystemUIFactory会负责创建各种依赖)
                    //2. 然后马上注入SystemUIAppComponentFactory所需的成员(即
                    //	ContextComponentHelper)
                    SystemUIFactory.createFromConfig(context);
                    SystemUIFactory.getInstance().getSysUIComponent().inject(
                            SystemUIAppComponentFactory.this);
                }
        );
    }

    return app;
}

从上面我们看见了SystemUIFactory调用静态方法createFromConfig进行创建。从名字也能猜测一二:从配置中创建SystemUIFactory

唉,这个就值得思考了,为何要从配置中创建?难道可以配置成不同的SytemUIFactory吗?每个SystemUIFactory有什么区别吗?

我们带着问题往下看

SystemUIFactory

SystemUIFactory从名字上,似乎是SystemUI的工厂类。在上一篇文章Android 12 源码分析 ------ 应用层 二(SystemUI大体组织和启动过程):http://t.csdn.cn/AuzsL的自定义组件小节中,我们自定以的组件继承了SystemUI

难道SystemUIFactory是它的工厂类?

我们来看看源码,为了减少干扰,我们从上一小节中的createFromConfig方法开始查看,如下

java 复制代码
public static void createFromConfig(Context context) {
    createFromConfig(context, false);
}

@VisibleForTesting
//最终调用的地方
public static void createFromConfig(Context context, boolean fromTest) {
    //1. 如果SystemUIFactory,即mFactory,已经存在,则什么也不做
    if (mFactory != null) {
        return;
    }

    //2. 倘若1不满足,则读取配置文件中的类名,然后使用反射创建这个对象
    //config_systemUIFactoryComponent的值即为com.android.systemui.SystemUIFactory
    //那么请思考,是不是还有另外的类名,事实上是有的,还可以为:
    //com.android.systemui.tv.TvSystemUIFactory.我们后面来比较他们之间的区别
    final String clsName = context.getString(R.string.config_systemUIFactoryComponent);
    if (clsName == null || clsName.length() == 0) {
        throw new RuntimeException("No SystemUIFactory component configured");
    }

    //3. 创建完成对象之后,则调用init方法
    try {
        Class<?> cls = null;
        cls = context.getClassLoader().loadClass(clsName);
        mFactory = (SystemUIFactory) cls.newInstance();
        mFactory.init(context, fromTest);
    } catch (Throwable t) {
        Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t);
        throw new RuntimeException(t);
    }
}

接下来,继续进入其初始化函数中,如下:

java 复制代码
@VisibleForTesting
    public void init(Context context, boolean fromTest)
            throws ExecutionException, InterruptedException {
        //是否要运行初始化的一个判断,全部满足下面的条件则初始化
        //1. 非测试模块运行
        //2. 是主用户
        //3. 是主进程
        mInitializeComponents = !fromTest
                && android.os.Process.myUserHandle().isSystem()
                && ActivityThread.currentProcessName().equals(ActivityThread.currentPackageName());
        //又见GlobalRootComponent。在上一篇文章中已经提及过
        //这里就是去构建整个应用最最顶层的那个Component
        mRootComponent = buildGlobalRootComponent(context);
        //从GlobalRootComponent中,获取需要创建依赖的Builder。然后创建依赖

        //1. 先创建WmComponent (这是一个与SysUIComponent站在同一维度的Component,它负责提供WindowManager相关的东西,此处可不用太过在意,后面会详解)
        mWMComponent = mRootComponent.getWMComponentBuilder().build();
        if (mInitializeComponents) {
            //然后初始化
            mWMComponent.init();
        }

        //2. 再创建SysUIComponent
        SysUIComponent.Builder builder = mRootComponent.getSysUIComponent();
        if (mInitializeComponents) {
            //将需要的各种食材,放入Builder,最后build()一下就是最终对象
            //使用Builder,可以不用考虑这些函数的调用顺序,他们会在Builder类中被处理好
            builder = prepareSysUIComponentBuilder(builder, mWMComponent)
                    .setPip(mWMComponent.getPip())
                    .setLegacySplitScreen(mWMComponent.getLegacySplitScreen())
                    .setSplitScreen(mWMComponent.getSplitScreen())
                    .setOneHanded(mWMComponent.getOneHanded())
                    .setBubbles(mWMComponent.getBubbles())
                    .setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
                    .setShellCommandHandler(mWMComponent.getShellCommandHandler())
                    .setAppPairs(mWMComponent.getAppPairs())
                    .setTaskViewFactory(mWMComponent.getTaskViewFactory())
                    .setTransitions(mWMComponent.getTransitions())
                    .setStartingSurface(mWMComponent.getStartingSurface())
                    .setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper());
        } else {
            
            builder = prepareSysUIComponentBuilder(builder, mWMComponent)
                    .setPip(Optional.ofNullable(null))
                    .setLegacySplitScreen(Optional.ofNullable(null))
                    .setSplitScreen(Optional.ofNullable(null))
                    .setOneHanded(Optional.ofNullable(null))
                    .setBubbles(Optional.ofNullable(null))
                    .setHideDisplayCutout(Optional.ofNullable(null))
                    .setShellCommandHandler(Optional.ofNullable(null))
                    .setAppPairs(Optional.ofNullable(null))
                    .setTaskViewFactory(Optional.ofNullable(null))
                    .setTransitions(Transitions.createEmptyForTesting())
                    .setStartingSurface(Optional.ofNullable(null))
                    .setTaskSurfaceHelper(Optional.ofNullable(null));
        }
        //创建,然后初始化
        mSysUIComponent = builder.build();
        if (mInitializeComponents) {
            mSysUIComponent.init();
        }

        //3. 通过SysUIComponent获得Dependency对象,然后调用start()函数进行初始化,
        //	(似乎叫做init()函数更加合理一点)
        Dependency dependency = mSysUIComponent.createDependency();
        dependency.start();
    }

在SystemUIFactory.init()函数中,主要做了四件事:

  1. 创建并初始化GlobalRootComponent
  2. 创建并初始化WMComponent
  3. 创建并初始化SysUIComponent
  4. 创建并初始化Dependency

这4个对象,即为SystemUI整个应用需要用到的组件,通过这4个组件,就可以得到Dagger2中的各种各样的依赖。

在挨个介绍这4个对象之前。我们先处理一下前面的疑问,分别有:

  1. SystemUIFactory为何要从配置中创建?
  2. SystemUIFactory的命名,是不是感觉有些奇怪了?

回答问题1:因为SystemUIFactory不仅仅可以直接实例化SysetmUIFactory,有时还需要实例化SystemUIFactory的子类(比如TvSystemUIFactory),之所以需要有一个TvSystemUIFactory,是因为它需要一个不同版本的GlobalRootComponent叫做TvGloabRootComponent.而这个TvGlobalRootComponent继承于GlobalRootComponent

回答问题2:显然SystemUIFactory提供的实例创建更应该叫GloablRootComponentFactory。而不应该叫SystemUIFactory.我想这也是开发人员,不够严谨的地方。

当然,也可能还有我未理解到的意思

此时,SystemUIFactory其实已经没有什么内容可以介绍了,剩下的内容无外乎getter,内容简单,此处略过

接下来就是几个Component的创建过程了

GlobalRootComponent

GlobalRootComponent的创建,需要从它的图说起。在Android 12 源码分析 ------ 应用层 二(SystemUI大体组织和启动过程):http://t.csdn.cn/AuzsL一文中,我们给GlobalRootComponent定义了一个Builder接口。

如下:

java 复制代码
@Singleton
@Component(modules = {
        GlobalModule.class,
        SysUISubcomponentModule.class,
        WMModule.class})
public interface GlobalRootComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder context(Context context);

        GlobalRootComponent build();
    }

    //省略无关紧要部分
}

那么Dagger2对这个Builder是怎么生成的呢?

Dagger2生成的GlobalRootComponent.Builder

在编译的过程中,上面的Builder接口,将会被Dagger2实现,并生成一个名叫Builder的类。如下:

该类位于:

out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/kapt/gen/sources/com/android/systemui/dagger/DaggerGlobalRootComponent.java
java 复制代码
private static final class Builder implements GlobalRootComponent.Builder {
    private Context context;

    @Override
    public Builder context(Context context) {
      //1. 先判断传入的参数是否为空
      //2. 将传入的参数,赋值给内成员(这也是在上一篇文章中提及的BindsInstance的语义)
      this.context = Preconditions.checkNotNull(context);
      return this;
    }

    @Override
    public GlobalRootComponent build() {
      //1. 先判断context是否为空
      //2. new一个DaggerGlobalRootComponennt对象,该对象就是Dagger2中实现
      //	GlobalRootComponent接口的对象
      Preconditions.checkBuilderRequirement(context, Context.class);
      return new DaggerGlobalRootComponent(new GlobalModule(), context);
    }
  }

接下来我们看看Dagger2对GlobalRootComponent的实现细节。

Dagger2生成的GlobalRootComponent

生成的文件位于:

out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/kapt/gen/sources/com/android/systemui/dagger/DaggerGlobalRootComponent.java

内容特别多,为了简化分析,我会缩进部分代码,并对其中的实现细节进行简化,因为他们的实现和前面介绍的模板几乎没有差别,现在只需对其结构进行了解。

java 复制代码
public final class DaggerGlobalRootComponent implements GlobalRootComponent {
  
    //定义一个成员变量,类型为Provider<T> 它可以通过
    //Provider<T>.get() 得到对应的具体的对象
    //正是这个get()函数,可以让成员真正被需要的时候才初始化
    //这样可以减少内存的使用
    //可将其理解为:Context的提供者(同前面的模板一起理解,几乎可以肯定,它的实现为
    //							DoubleCheck类)
    private Provider<Context> contextProvider;

    //省略余下的类似的成员定义


  //构造器函数,Dagger2根据我们画的图,会正确的处理构造函数所需的依赖
  private DaggerGlobalRootComponent(GlobalModule globalModuleParam, Context contextParam) {
    this.context = contextParam;
    initialize(globalModuleParam, contextParam);
  }

    //辅助构造函数的方法,用于初始化成员变量
  @SuppressWarnings("unchecked")
  private void initialize(final GlobalModule globalModuleParam, final Context contextParam) {
    //在方法体中,Dagger2根据我们画的图,自动去找寻需要的对象,并初始化本对象成员
    //这也正是Dagger2的最大作用,它可以简化我们的代码编写。自动帮我们完成各种各样的依赖
    //方法体中的赋值相对简单。不做过多介绍
    //这里面其实就是:使用DoubleCheck对成员进行初始化(结合前面的模板进行思考)
  } 

  
  //同构造函数一样,mainResources你也不需要知道为什么会出现在这个地方(这属于Dagger2的内部
  //				细节)。Dagger2会自动处理好对于这个函数的调用
  private Resources mainResources() {
    //AAA_BBBFactory通常表示,AAA类的BBB方法的工厂类,它实现了Factory<T>接口
    return FrameworkServicesModule_ProvideResourcesFactory.provideResources(context);
  }

  //同MainResources()函数一样,Dagger2自动处理好其调用
  private Executor mainExecutor() {
    return GlobalConcurrencyModule_ProvideMainExecutorFactory.provideMainExecutor(context);
  }

  //这个是实现的GlobalRootComponent的接口.在这个接口中,直接new了一个对象并返回
  //倘若每次调用这个方法,则会创建不同的对象。这是因为他们的生命周期不一样
  //GlobalRootComponent的生命周期为@SingleTton
  //而WMComponent.Builder的生命周期为@WMSingleton
  @Override
  public WMComponent.Builder getWMComponentBuilder() {
    return new WMComponentBuilder();
  }

  //同WMComponent.Builder一样,直接new了一个对象返回,因为其生命周期为
  //@SysUISingleton
  @Override
  public SysUIComponent.Builder getSysUIComponent() {
    return new SysUIComponentBuilder();
  }

  //对GlobalRootComponent的接口方法的实现。在实现中,使用了ThreadFactoryImpl_Factory类来
  //实例化对象
  
  //这里可能就会有以问题了,为何不是直接new一个对象,反而用了ThreadFactoryImpl_Factory来实例化
  //因为在GlobalConcurrencyModule里面有如下的绑定关系
  //@Binds
  //public abstract ThreadFactory bindExecutorFactory(ThreadFactoryImpl impl)
  //在需要ThreadFactory的时候,就会创建ThreadFactoryImpl实例。而ThreadFactoryImpl实例,
  //则由
  
  //其对应的工厂类(ThreadFactoryImpl_Factory)来创建
  @Override
  public ThreadFactory createThreadFactory() {
    return ThreadFactoryImpl_Factory.newInstance();
  }

  //返回一个为空的Optional
  private static <T> Provider<Optional<T>> absentJdkOptionalProvider() {
    @SuppressWarnings("unchecked") // safe covariant cast
    Provider<Optional<T>> provider = (Provider<Optional<T>>) ABSENT_JDK_OPTIONAL_PROVIDER;return provider;
  }

  //使用Provider包装一个非空的Optional,所有操作最后都会调用到其内部的delegate
  private static final class PresentJdkOptionalInstanceProvider<T> implements Provider<Optional<T>> {}

  //暂时未知
  private static final class PresentJdkOptionalLazyProvider<T> implements Provider<Optional<Lazy<T>>> {}

  //实现Builder接口
  //各个接口,只是简单的setter
  private static final class Builder implements GlobalRootComponent.Builder {}

  //实现接口
  private final class WMComponentBuilder implements WMComponent.Builder {}

  //实现子组件,只要是其子组件,就在内部实现一个非静态的类,因为subcomponent含有
  //component的所有依赖关系,因此需要实现为一个内部类,这样它就会持有一个对外部类的引用
  //同理,WMComponentImpl的subcomponent也会在其内部出现
  private final class WMComponentImpl implements WMComponent {}

  //实现Builder
  private final class SysUIComponentBuilder implements SysUIComponent.Builder {}

  //实现子组件
  private final class SysUIComponentImpl implements SysUIComponent {}
}

在对GlobalRootImpl接口的实现中,分别完成了如下的工作:

  1. 根据Dagger2中的图实现对应的构造函数
  2. 根据Dagger2中的图实现对应的接口方法
  3. 对subcomponent,将其实现为内部类
  4. 对各个Builder接口,进行实现

从上我们也可以看到,其和我们的Demo模板的生产,差异不大,只是体量变大了很多

接下来看看WMComponent的实现

WMComponent

WMComponent的定义如下

java 复制代码
@WMSingleton
@Subcomponent(modules = {WMShellModule.class})
public interface WMComponent {

    //@Subcomponent.Builder定义了Builder接口
    //在上面,已经看到了WMComponent.Builder的接口实现了
    @Subcomponent.Builder
    interface Builder {
        WMComponent build();
    }

    //默认方法,用来初始化整个Shell.此处可以暂时不用管Shell对应的逻辑语义
    //实际上,你可以将其理解为对WindowManager的部分功能的封装并提供接口让用户与WM可以交互
    //犹如Bash shell(Bourne-Again Shell)在OS中的作用
    default void init() {
        getShellInit().init();
    }

    //用来获取ShellInit的实现,它只会在上面的init函数中被调用
    //ShellInit的抽象:表示对Shell进行初始化的一个入口点。
    @WMSingleton
    ShellInit getShellInit();

    //返回一个Optional<ShellCommandHandler>对象
    @WMSingleton
    Optional<ShellCommandHandler> getShellCommandHandler();

    //省略类似部分
}

在上面的图中,我们"绘制"了WMComponent的Builder接口,同时还绘制了可以获取ShellInit的接口。

在查看Dagger2生成的代码之前,我们看看,我们是怎么绘制图,让Dagger2来生成ShellInit的。

再次注意:ShellInit的抽象表示的是WMShell的一个入口对象。

从上面的代码可以知道,WMComponent的模块有WMShellModule。直接搜寻其源码,查看是否有ShellInit的返回,发现并没有。但是WMShellModule的还包含一个WMShellBaseModule在其中可以搜寻到ShellInit的返回。如下

WMShellBaseModule

WMShellBaseModuel,告诉了Dagger2如何创建ShellInit对象,如下

java 复制代码
@Module
public abstract class WMShellBaseModule{

    //省略部分代码

    //通过@Provides告诉Dagger2,当需要ShellInit的时候,将会调用本函数
    //即返回ShellInitImpl的asShellInit()方法
    //而ShellInitImpl的对象,则通过下一个方法进行提供
    @WMSingleton
    @Provides
    static ShellInit provideShellInit(ShellInitImpl impl) {
        return impl.asShellInit();
    }

    //告诉Dagger2如果需要ShellInitImpl对象的时候,则由本方法提供
    //在本方法中,通过new一个ShellInitImpl对象来创建对应的ShellInitImpl
    @WMSingleton
    @Provides
    static ShellInitImpl provideShellInitImpl(DisplayImeController displayImeController,
            DragAndDropController dragAndDropController,
            ShellTaskOrganizer shellTaskOrganizer,
            Optional<BubbleController> bubblesOptional,
            Optional<LegacySplitScreenController> legacySplitScreenOptional,
            Optional<SplitScreenController> splitScreenOptional,
            Optional<AppPairsController> appPairsOptional,
            Optional<PipTouchHandler> pipTouchHandlerOptional,
            FullscreenTaskListener fullscreenTaskListener,
            Transitions transitions,
            StartingWindowController startingWindow,
            @ShellMainThread ShellExecutor mainExecutor) {
        return new ShellInitImpl(displayImeController,
                dragAndDropController,
                shellTaskOrganizer,
                bubblesOptional,
                legacySplitScreenOptional,
                splitScreenOptional,
                appPairsOptional,
                pipTouchHandlerOptional,
                fullscreenTaskListener,
                transitions,
                startingWindow,
                mainExecutor);
    }
}

从上面的代码可以知道,WMShell的初始化入口点,是ShellInitImpl的asShellInit()方法返回的对象.至于该对象内部是如何进行初始化的,会在合适的时候介绍到,现在我们专注于WMComponent的各种初始化上

同理对WMComponent中的其他接口方法,实现细节类似。

接下来看看Dagger2对WMComponenet相关代码的实现。首先是其Builder的实现

Dagger2生成的WMComponent.Builder

在前文中的GlobalRootComponent的实现中,我们看到了WMComponent.Builder的实现,现将其内容展现如下:

java 复制代码
public final class DaggerGlobalRootComponent implements GlobalRootComponent{

  //省略部分代码

  private final class WMComponentBuilder implements WMComponent.Builder{
    @Override
    public WMComponent build(){
      //直接new一个WMComponentImpl,这个对象是对WMComponent接口的实现
      return new WMComponentImpl();
    }
  }

  //省略部分代码
}

接下来看看,Dagger2对WMComponent接口的实现。

Dagger2生成的WMComponent

WMComponent作为GlobalRootComponent的subcomponent,则WMComponent被放置在了DaggerGlobalRootComponent的内部,如下:

java 复制代码
public final class DaggerGlobalRootComponent implements GlobalRootComponent{

  //省略部分代码

    private final class WMComponentImpl implements WMComponent {

      //同component一样,将成员定义成Provider的封装
      //只要在需要的时候才通过其Provider<T>.get()方法获取其内部的实现
      private Provider<Handler> provideShellMainHandlerProvider;

      //省略相似代码

      //生成的构造函数,通过调用initialize()方法进行初始化
      private WMComponentImpl() {

        initialize();
      }

      //对内部的成员进行初始化
      @SuppressWarnings("unchecked")
      private void initialize() {
        //Dagger2自动找到需要的依赖,然后对本对象的成员,进行赋值初始化操作
      }

      //实现其对应的接口
      @Override
      public ShellInit getShellInit() {
        return provideShellInitProvider.get();
      }

      //省略其他相似代码
    }
  //省略部分代码
}

从上面生成的代码中,我们看一看到WMComponent这个subcomponent 几乎和GlobalRootComponent的结构一致。

而这些生成内的东西,现在不需要关系,我们只需要知道其结构和大体抽象代码,在真正的业务实现细节中,会在有需要的地方进行提及。

再次提醒:WMComponent为Window Manager提供给SystemUI的交互接口。现在只需知道这一层抽象意义即可

接下来继续看看SysUIComponent.

SysUIComponent

先看看源码中,是如何定义SysUIComponent的,即我们如何绘制SysUIComponent的,如下:

java 复制代码
@SysUISingleton
@Subcomponent(modules = {
        DefaultComponentBinder.class,
        DependencyProvider.class,
        SystemUIBinder.class,
        SystemUIModule.class,
        SystemUIDefaultModule.class})
public interface SysUIComponent {

    //又来Builder模式
    //并传递WMComponent中相应的组件给SysUIComponent
    //正是基于此,WMComponent组件的初始化必须在SysUIComponent组件之前完成
    //且可以通过提供Optional<?>.empty()来替换其中的组件,这也是SystemUIFactory中的init()
    //函数中的部分代码
    @SysUISingleton
    @Subcomponent.Builder
    interface Builder {
      //绑定实例,内容如前文,对应的语义见上一篇博文<http://t.csdn.cn/4LyLq>
        @BindsInstance
        Builder setPip(Optional<Pip> p);
        //省略一些相似代码

        //build函数,返回SysUIComponent接口的实现
        //其实,仔细看过前面的WMComponent就会知道,返回的实例多半叫做SysUIComponentImpl
        SysUIComponent build();
    }

    //默认的初始化操作,为了保持跟WMComponent一致的操作步调,这里依然有一个init()接口
    //但是它的函数体为空
    default void init() {
        // Do nothing
    }

    //返回一个BootCompleteCacheImpl对象
    //这个对象,我们在前一篇博文<http://t.csdn.cn/4LyLq>中介绍过,用于缓存是否所有的
    //SystemUI服务都已经启动完成
    
    //其实,这里读者可以思考一下,是否BootCompleteCacheImpl对象还会再需要?如果不需要了,
    //它能被GC回收吗?
    
    //如果不能回收,是不是代表BootCompleteCacheImpl的生命周期不应该这样设置?
    @SysUISingleton
    BootCompleteCacheImpl provideBootCacheImpl();

   //返回一个Dependency对象
   //Dependency对象,提供了SystemUI各个组件的快捷访问,后文我们将会其进行详细介绍
    @SysUISingleton
    Dependency createDependency();

   //省略相同的代码
  
    //inject接口,表示对PeopleProvider对象中,注入被@Inject标记的成员
    void inject(PeopleProvider peopleProvider);
}

其实有了上面的注释,以及前面的模板,读者应该已经知道了Dagger2对上面的一些生成代码了。

接下来我们会先看对应的Builder接口的生成,然后再看SysUIComponent接口的生成

Dagger2生成的SysUIComponent.Builder

SysUIComponent.Builder接口依然在DaggerGlobalRootComponent类中,如下:

java 复制代码
private final class SysUIComponentBuilder implements SysUIComponent.Builder {
    
    //成员的定义,省略
    //定义必要的成员,用于在build阶段生成最终的SysUIComponentImpl

    //各种setter接口函数的实现,用于保存传入的参数,很简单,省略

    //接口的build函数实现,先检查,然后new一个SysUIComponentImpl对象
    @Override
    public SysUIComponent build() {
      Preconditions.checkBuilderRequirement(setPip, Optional.class);
      Preconditions.checkBuilderRequirement(setLegacySplitScreen, Optional.class);
      Preconditions.checkBuilderRequirement(setSplitScreen, Optional.class);
      Preconditions.checkBuilderRequirement(setAppPairs, Optional.class);
      Preconditions.checkBuilderRequirement(setOneHanded, Optional.class);
      Preconditions.checkBuilderRequirement(setBubbles, Optional.class);
      Preconditions.checkBuilderRequirement(setTaskViewFactory, Optional.class);
      Preconditions.checkBuilderRequirement(setHideDisplayCutout, Optional.class);
      Preconditions.checkBuilderRequirement(setShellCommandHandler, Optional.class);
      Preconditions.checkBuilderRequirement(setTransitions, ShellTransitions.class);
      Preconditions.checkBuilderRequirement(setStartingSurface, Optional.class);
      Preconditions.checkBuilderRequirement(setTaskSurfaceHelper, Optional.class);
      return new SysUIComponentImpl(new DependencyProvider(), new NightDisplayListenerModule(), new UserModule(), setPip, setLegacySplitScreen, setSplitScreen, setAppPairs, setOneHanded, setBubbles, setTaskViewFactory, setHideDisplayCutout, setShellCommandHandler, setTransitions, setStartingSurface, setTaskSurfaceHelper);
    }
  }

Builder函数的实现很是简单

  1. 保存必要的中间对象,如各种Optional<T>
  2. new一个SysUIComponent接口的实现

接下来看看SysUIComponent的实现,其实到这里,大家已经非常熟悉了,它的结构等同于GlbalRootComponent,也等同于WMComponent

Dagger2生成的SysUIComponent

作为GlobalRootComponent的subcomponent,所以SysUIComponent的生成依然在DaggerGlobalRootComponent中,如下

java 复制代码
public final class DaggerGlobalRootComponent implements GlobalRootComponent {

  //省略不相干的部分

  private final class SysUIComponentImpl implements SysUIComponent {
    
    //省略成员定义,其结构和内容,相似于GlobalRootComponent和WMComponent,故不再啰嗦

    //对应的构造函数
    private SysUIComponentImpl(DependencyProvider dependencyProviderParam,
        NightDisplayListenerModule nightDisplayListenerModuleParam, UserModule userModuleParam,
        Optional<Pip> setPipParam, Optional<LegacySplitScreen> setLegacySplitScreenParam,
        Optional<SplitScreen> setSplitScreenParam, Optional<AppPairs> setAppPairs,
        Optional<OneHanded> setOneHandedParam, Optional<Bubbles> setBubblesParam,
        Optional<TaskViewFactory> setTaskViewFactoryParam,
        Optional<HideDisplayCutout> setHideDisplayCutoutParam,
        Optional<ShellCommandHandler> setShellCommandHandlerParam,
        ShellTransitions setTransitionsParam, Optional<StartingSurface> setStartingSurfaceParam,
        Optional<TaskSurfaceHelper> setTaskSurfaceHelper) {
        //因为成员函数过多,因此分成了7个初始化辅助函数进行初始化
    }

    //initialize,initialize1,initialize2,initialize3,initialize4,initialize5,
    //initialize6
    //这几个函数都是用于初始化成员的,其中初始化成员的方法和过程,跟GlobalRootComponent
    //和WMComponent类似
    @SuppressWarnings("unchecked")
    private void initialize()
        

    //实现的接口,省略,较简单


    //对PeopleProvider中被@Inject标注的成员,进行赋值
    @Override
    public void inject(PeopleProvider peopleProvider) {
      injectPeopleProvider(peopleProvider);
    }

    //使用辅助类 Type_MembersInjector。进行成员的赋值
    //PeopleProvider_MembersInjector.injectMPeopleSpaceWidgetManager()的实现就为:
    //instance.mPeopleSpaceWidgetManager = mPeopleSpaceWidget;
    private PeopleProvider injectPeopleProvider(PeopleProvider instance) {
      PeopleProvider_MembersInjector.injectMPeopleSpaceWidgetManager(instance, peopleSpaceWidgetManagerProvider.get());
      return instance;
    }

    //SysUIComponent的subcomponent的builder的实现
    private final class ExpandableNotificationRowComponentBuilder implements ExpandableNotificationRowComponent.Builder {}

    //SysUIComponent的subcomponent的实现
    private final class ExpandableNotificationRowComponentImpl implements ExpandableNotificationRowComponent {}

    //SysUIComponent的subcomponent的Factory的实现
    private final class KeyguardBouncerComponentFactory implements KeyguardBouncerComponent.Factory {}

    //SysUIComponent的subcomponent的实现
    private final class KeyguardBouncerComponentImpl implements KeyguardBouncerComponent {}

    //省略相似部分
  }
}

从上面的生成结果中,我们可以看到,SysUIComponent的生成,跟GlobalRootComponent很是类似。主要完成:

  1. 其内部subcomponent的Bulider的实现
  2. 其内部subcomponent的Factory的实现
  3. 其内部subcomponent的实现
  4. 其内部接口方法的实现

有了上面的介绍,现在基本上已经非常明确,各个组件的初始化过程和内部实现细节了。

接下来还剩下最后一个Dependency的实现细节

Dependency

Dependency对应的抽象是什么?这里直接给出一个结论:为了方便在各个模块中能够直接引用Dagger2中的依赖。举个例子,如果我要通过SysUIComponent访问某个依赖,则可能出现如下的调用情况:

java 复制代码
d=sysuicomponent.getxxx().getxxx().getxxx().getxxx();
d.xxx();

上面的代码中,出现了多层的getxxx()函数,因此,为了方便,将一些常见的依赖,通过Dependency来调用即可。现在提供的方法为:Dependency.get(依赖.class)从而获得对应的依赖

这也是这个类的名字的由来。

有了上面的观点就非常容易看懂Dependency.java文件了

如下:

java 复制代码
@SysUISingleton
public class Dependency {
    
    //一些简单的成员定义,省略

    //由Dagger2进行创建
    @Inject
    public Dependency() {
    }

    //初始化各个依赖
    protected void start() {
        //mProviders是一个以Object为对象,以LazyDependencyCreator为值的Map
        //LazyDependencyCreator封装创建依赖的方法,用于在需要的时候创建
        mProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get);
        //省略相似部分

        //将Dependency对象保存在Static字段中,便于访问
        Dependency.setInstance(this);
    }

    //省略一些简单的函数


    //当访问某个具体的依赖时,最终的访问点
    private synchronized <T> T getDependencyInner(Object key) {
        @SuppressWarnings("unchecked")
        //1. 首先检查依赖的缓存中,是否有对应的依赖,其中缓存使用了ArrayMap进行存储(注意其和
        //	HashMap之间的差别)
        //2. 如果没有,调用createDependency创建
        T obj = (T) mDependencies.get(key);
        if (obj == null) {
            obj = createDependency(key);
            //3. 如果创建完成,就将其加入缓存中,方便未来调用。注意此处有同步控制,防止并发
            //	带来的问题
            mDependencies.put(key, obj);

            //4. 如果某些依赖,需要使用dump功能,则将其注册到DumpManager。如同
            //	SystemUIService中的初始化最后部分一样
            if (autoRegisterModulesForDump() && obj instanceof Dumpable) {
                mDumpManager.registerDumpable(obj.getClass().getName(), (Dumpable) obj);
            }
        }
        return obj;
    }

    //创建依赖的具体实现
    @VisibleForTesting
    public <T> T createDependency(Object cls) {
      //1. 检查参数,必须是DependencyKey类型或者Class类型
        Preconditions.checkArgument(cls instanceof DependencyKey<?> || cls instanceof Class<?>);

        //2. 通过key,得到LazyDependencyCreator对象。这个对象通常封装着一个用于创建具
        //	体对象的方法。如Lazy<T>的get()方法
        @SuppressWarnings("unchecked")
        LazyDependencyCreator<T> provider = mProviders.get(cls);
        if (provider == null) {
            throw new IllegalArgumentException("Unsupported dependency " + cls
                    + ". " + mProviders.size() + " providers known.");
        }
        //3. 调用封装的方法(如Lazy<T>.get()),创建具体的对象
        return provider.createDependency();
    }

    //定义延迟创建的一种封装形式
    private interface LazyDependencyCreator<T> {
        T createDependency();
    }

    //对依赖的key的封装
    public static final class DependencyKey<V> {
        private final String mDisplayName;

        public DependencyKey(String displayName) {
            mDisplayName = displayName;
        }

        @Override
        public String toString() {
            return mDisplayName;
        }
    }

    //省略掉一些简单的代码
}

从上面可以知道,Dependency就做了两件事情:

  1. 缓存需要用的依赖的Lazy<T>封装
  2. 缓存需要用的依赖的具体实例。
  3. 然后在需要的时候通过get()函数,即可得到相应的依赖

至此,我们介绍了SystemUIFactory的init()方法中,重要组件的创建和初始化细节。也完成了整个SystemUI的启动

现在将整个启动过程,总结如下:

  1. system_server启动之后,开始启动各种服务
  2. 在启动其他服务的时候,会先通过PackageManager,获得要启动systemui的组件名字,然后根据名字启动systemui组件
  3. 在上面一步获得的名字就是SystemUIService。
  4. 启动SystemUIService,则会先创建SystemUIApplication,在创建之前会先调用SystemUIAppComponentFactory添加相应的依赖注入
  5. SystemUIApplication创建之后,通过调用SystemUIFactory.init() 方法初始化Dagger2中的依赖。(本文的内容)
  6. 同时在SystemUIApplication中会监听系统的启动广播。
  7. 接着创建SystemUIService,再创建之前,还会先调用SystemUIAppComponentFactory相应的方法,添加依赖注入
  8. 创建SystemUIService之后,通过SystemUIApplication启动各种服务

接下来,我们将进入SystemUI的UI部分。看看状态栏是如何被加入整个屏幕的。然后一步步拆分,查看下拉状态栏中的各个图标的实现

因为最近要上课,尽量保持一周一更