Android 12 source code analysis - application layer three (SystemUIFactory and its Dependency analysis)

Android 12 source code analysis - application layer three (SystemUIFactory and its Dependency analysis)

In the previous article, the startup process of SystemUI was introduced, and Dagger2 was briefly mentioned to manage the dependencies used in each SystemUI. And this part of the code is in: mContextAvailableCallback.onContextAvailable(this); process. We only briefly touched on this part of the process without analyzing it in detail.

Next, starting from this call, we will introduce the initialization of Component and subcomponent in SystemUI, and understand how to use these Components.

This article will first use an example to briefly introduce the generation template for each annotation in Dagger2, then introduce the creation process of important components and subcomponents in SystemUI, and finally transition to a key class Dependency.

Note: The reason why we use another example to illustrate the generated template of Dagger2 is entirely because Dagger2 generates too much code for SystemUI, which makes it difficult to document.

Understand Dagger2's templates

In order to better understand Dagger2's code-generated template, we write according to the following example, and then view the generated classes.

Put the following code into a file DemoComponent.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(){
    
    

    }
}

With the picture drawn above, let's check the files generated by Dagger2 based on the picture. The generated files are:

  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

Next, let's check the generated 7 files one by one, what are the contents, and the remaining 6 classes will be used in DaggerDemoComponent.java. Therefore, let's look at the remaining 6 classes first, and finally look at DaggerDemoFactory.java

DemoAClass_Factory,DemoBClass_Factory,DemoBinds_Factory

The source code of DemoAClass_Factory is as follows:

//对于任何类来讲,只要其构造函数带有@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 are exactly the same as DemoAClass_Factory, no more verbosity.

DemoInject_MembersInjector

DemoInject_MembersInjector is used for the injection of auxiliary members, because the following code in the DemoInject class

class DemoInject{
    
    
    @Inject
    DemoAClass a;
}

The entire auxiliary class source code is as follows:


//每一个辅助注入的类,都是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;
  }
}

The above auxiliary injection class is also very simple, then read on

DemoSubComponent2_DemoModule2_GetProviderFactory

The DemoSubComponent2_DemoModule2_GetProviderFactory class represents the implementation factory class for @Provides. The source code is as follows:


//对于任何一个被@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());
  }
}

The above code is still very simple and no longer verbose.

DemoSubComponent2_DemoModule2_Proxy

DemoSubComponent2_DemoModule2_Proxy is the representation of the abstract module, the source code is as follows:

public final class DemoSubComponent2_DemoModule2_Proxy {
    
    
  private DemoSubComponent2_DemoModule2_Proxy() {
    
    
  }

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

In DemoModule2, there is nothing that needs to be implemented, and @Binds is semantically obvious enough, so the class generated above does not have any excess. simpler

Next, let’s see how DaggerDemoComponent uses the classes created above to handle the dependencies between them.

DaggerDemoComponent

DaggerDemoComponent is the entry point of the entire dependency injection, and its source code is as follows:

//实现我们的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();
    }
  }
}

The following work is completed in Component:

  1. Implemented component, subcomponent, and their corresponding Builder and Factory classes. Subcomponent is the internal class of component.
  2. Implement the corresponding interface methods. These methods will be delegated to other xxx_Factory and xxxx_MembersInjector auxiliary classes to complete.
  3. The entrusted xxx_Factory factory class and xxx_MembersInjector auxiliary class will be correctly initialized

At this point, we have an overall understanding of the template generated by Dagger2, and have made some comments on the implementation details.

Next, let's continue to look at the creation process of important components in SystemUI

SystemUI is the starting point for creating Dagger2 dependencies

In the first article, we took a look at mContextAvailableCallback.onContextAvailable(this) in SystemUIApplication.onCreate().

This is the starting point for Dagger2 to create dependencies, the assignment of mContextAvailableCallback, in SystemUIAppComponentFactory.java.

as follows:

@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;
}

From the above we saw that SystemUIFactory calls the static method createFromConfig to create. You can guess one or two from the name: Create SystemUIFactory from configuration

Alas, this is worth thinking about, why create it from the configuration? Can it be configured as a different SytemUIFactory? Is there any difference for each SystemUIFactory?

Let’s look down with questions

SystemUIFactory

From the name, SystemUIFactory seems to be the factory class of SystemUI. In the previous article Android 12 source code analysis - Application layer 2 (General organization and startup process of SystemUI): In the custom component section of http://t.csdn.cn/AuzsL , our custom component inherits SystemUI

Is SystemUIFactory its factory class?

Let's take a look at the source code. In order to reduce interference, we start with the createFromConfig method in the previous section, as follows

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);
    }
}

Next, continue to enter its initialization function, as follows:

@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();
    }

In the SystemUIFactory.init() function, there are four main things:

  1. Create and initialize GlobalRootComponent
  2. Create and initialize WMComponent
  3. Create and initialize SysUIComponent
  4. Create and initialize Dependency

These 4 objects are the components that SystemUI needs to use in the entire application. Through these 4 components, you can get various dependencies in Dagger2.

Before introducing these 4 objects one by one. Let's deal with the previous questions first, which are:

  1. Why is SystemUIFactory created from configuration?
  2. Does the naming of SystemUIFactory feel a little strange?

Answer question 1: Because SystemUIFactory can not only directly instantiate SysetmUIFactory, but sometimes also needs to instantiate subclasses of SystemUIFactory (such as TvSystemUIFactory). The reason why a TvSystemUIFactory is needed is because it requires a different version of GlobalRootComponent called TvGloabRootComponent. And this TvGlobalRootComponent Inherited from GlobalRootComponent

Answer question 2: Obviously, the instance creation provided by SystemUIFactory should be called GloablRootComponentFactory. It should not be called SystemUIFactory. I think this is also a place where developers are not rigorous enough.
Of course, there may be other meanings that I don't understand.

At this point, SystemUIFactory actually has nothing to introduce, the rest of the content is nothing more than getter, the content is simple, skip it here

Next is the creation process of several Components

GlobalRootComponent

The creation of GlobalRootComponent needs to start with its diagram. In the article Android 12 Source Code Analysis - Application Layer 2 (General Organization and Startup Process of SystemUI): http://t.csdn.cn/AuzsL , we defined a Builder interface for GlobalRootComponent.

as follows:

@Singleton
@Component(modules = {
    
    
        GlobalModule.class,
        SysUISubcomponentModule.class,
        WMModule.class})
public interface GlobalRootComponent {
    
    

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

        GlobalRootComponent build();
    }

    //省略无关紧要部分
}

So how does Dagger2 generate this Builder?

GlobalRootComponent.Builder generated by Dagger2

During the compilation process, the above Builder interface will be implemented by Dagger2 and a class named Builder will be generated. As follows:
The class is located at:

out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/kapt/gen/sources/com/android/systemui/dagger/DaggerGlobalRootComponent.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);
    }
  }

Next, let’s take a look at the implementation details of Dagger2’s GlobalRootComponent.

GlobalRootComponent generated by Dagger2

The generated files are located at:

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

There is a lot of content. In order to simplify the analysis, I will indent part of the code and simplify the implementation details, because their implementation is almost the same as the template introduced earlier, and now you only need to understand its structure.

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 {
    
    }
}

In the implementation of the GlobalRootImpl interface, the following work is completed:

  1. Implement the corresponding constructor based on the graph in Dagger2
  2. Implement the corresponding interface method according to the diagram in Dagger2
  3. For subcomponent, implement it as an inner class
  4. Implement each Builder interface

We can also see from the above that there is not much difference between its production and our Demo template, except that the volume has become much larger.

Next, look at the implementation of WMComponent

WMComponent

WMComponent is defined as follows

@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();

    //省略类似部分
}

In the above figure, we "draw" the Builder interface of WMComponent and also draw the interface that can obtain ShellInit.

Before looking at the code generated by Dagger2, let's take a look at how we draw the diagram and let Dagger2 generate ShellInit.

Note again: The abstract representation of ShellInit is an entry object of WMShell.

From the above code, we can know that the module of WMComponent has WMShellModule. Directly search its source code to see if there is a return from ShellInit, and find that there is not. But WMShellModule also contains a WMShellBaseModule in which the return of ShellInit can be searched. as follows

WMShellBaseModule

WMShellBaseModuel tells Dagger2 how to create a ShellInit object, as follows

@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);
    }
}

From the above code, we can know that the initialization entry point of WMShell is the object returned by the asShellInit() method of ShellInitImpl. As for how the object is initialized internally, we will introduce it at the appropriate time. Now we focus on the various functions of WMComponent Initialize

Similarly, for other interface methods in WMComponent, the implementation details are similar.

Next, let's look at Dagger2's implementation of WMComponenet related codes. The first is the implementation of its Builder

WMComponent.Builder generated by Dagger2

In the previous implementation of GlobalRootComponent, we saw the implementation of WMComponent.Builder, and its content is now shown as follows:

public final class DaggerGlobalRootComponent implements GlobalRootComponent{
    
    

  //省略部分代码

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

  //省略部分代码
}

Let's take a look at Dagger2's implementation of the WMComponent interface.

WMComponent generated by Dagger2

As the subcomponent of GlobalRootComponent, WMComponent is placed inside DaggerGlobalRootComponent, as follows:

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();
      }

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

From the code generated above, we can see that the subcomponent WMComponent has almost the same structure as the GlobalRootComponent.

These generated things do not need to be related now. We only need to know their structure and general abstract code. In the real business implementation details, we will mention them where necessary.

Reminder again: WMComponent is the interactive interface provided by Window Manager to SystemUI. Now you only need to know this abstract meaning

Next, continue to look at SysUIComponent.

SysUIComponent

First look at how SysUIComponent is defined in the source code, that is, how we draw SysUIComponent, as follows:


@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);
}

In fact, with the above comments and the previous templates, readers should already know some of the above generated codes by Dagger2.

Next, we will first look at the generation of the corresponding Builder interface, and then look at the generation of the SysUIComponent interface

SysUIComponent.Builder generated by Dagger2

The SysUIComponent.Builder interface is still in the DaggerGlobalRootComponent class, as follows:

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);
    }
  }

The implementation of the Builder function is very simple

  1. Save necessary intermediate objects, such as various Optional<T>
  2. newAn implementation of the SysUIComponent interface

Next, let’s take a look at the implementation of SysUIComponent. In fact, everyone is already very familiar with it. Its structure is equivalent to GlbalRootComponent and WMComponent.

SysUIComponent generated by Dagger2

As a subcomponent of GlobalRootComponent, the generation of SysUIComponent is still in DaggerGlobalRootComponent, as follows

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 {
    
    }

    //省略相似部分
  }
}

From the above generated results, we can see that the generation of SysUIComponent is very similar to GlobalRootComponent. Mainly completed:

  1. The implementation of the Bulider of its internal subcomponent
  2. The implementation of the Factory of its internal subcomponent
  3. The implementation of its internal subcomponent
  4. The implementation of its internal interface method

With the above introduction, it is basically very clear now, the initialization process and internal implementation details of each component.

Next, the implementation details of the last Dependency are left

Dependency

What is the abstraction corresponding to Dependency? Here is a direct conclusion: for convenience, dependencies in Dagger2 can be directly referenced in each module. For example, if I want to access a dependency through SysUIComponent, the following call situation may occur:

d=sysuicomponent.getxxx().getxxx().getxxx().getxxx();
d.xxx();

In the above code, there are multiple layers of getxxx() functions. Therefore, for convenience, some common dependencies can be called through Dependency. The method currently provided is: Dependency.get (dependency.class) to obtain the corresponding dependency

This is also the origin of the name of this class.

With the above point of view, it is very easy to understand the Dependency.java file.

as follows:

@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;
        }
    }

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

As you can see from the above, Dependency does two things:

  1. The cache needs to use the Lazy<T> package of dependencies
  2. Concrete instances of dependencies required for caching.
  3. Then when needed, you can get the corresponding dependencies through the get() function.

So far, we have introduced the details of the creation and initialization of important components in the init() method of SystemUIFactory. The startup of the entire SystemUI is also completed.

Now the entire startup process is summarized as follows:

  1. After system_server starts, it starts to start various services
  2. When starting other services, it will first obtain the name of the component to start systemui through PackageManager, and then start the systemui component according to the name
  3. The name obtained in the above step is SystemUIService.
  4. When SystemUIService is started, SystemUIApplication will be created first, and SystemUIAppComponentFactory will be called to add corresponding dependency injection before creation
  5. After SystemUIApplication is created, the dependencies in Dagger2 are initialized by calling the SystemUIFactory.init() method.(content of this article)
  6. At the same time, the system's startup broadcast will be monitored in SystemUIApplication.
  7. Then create SystemUIService. Before creating it, the corresponding method of SystemUIAppComponentFactory will be called to add dependency injection.
  8. After creating SystemUIService, start various services through SystemUIApplication

Next, we will enter the UI part of SystemUI. See how the status bar is added to the entire screen. Then split it step by step to see the implementation of each icon in the drop-down status bar

Since I have to go to class recently, I will try my best to update once a week.

Guess you like

Origin blog.csdn.net/xiaowanbiao123/article/details/132563581