Android 12 ソース コード分析 - アプリケーション層 3 (SystemUIFactory とその依存関係分析)
前回の記事では、SystemUI の起動プロセスを紹介し、各 SystemUI で使用される依存関係を管理するための Dagger2 について簡単に説明しました。コードのこの部分は、mContextAvailableCallback.onContextAvailable(this); プロセスにあります。プロセスのこの部分については、詳細には分析せずに簡単に触れただけです。
次に、この呼び出しから始めて、SystemUI のコンポーネントとサブコンポーネントの初期化を紹介し、これらのコンポーネントの使用方法を理解します。
この記事では、最初に例を使用して Dagger2 の各アノテーションの生成テンプレートを簡単に紹介し、次に SystemUI での重要なコンポーネントとサブコンポーネントの作成プロセスを紹介し、最後に主要なクラスの dependency に移行します。
注: Dagger2 の生成されたテンプレートを説明するために別の例を使用する理由は、Dagger2 が SystemUI 用に生成するコードが多すぎるため、文書化が困難になるためです。
Dagger2 テンプレートを理解する
Dagger2 のコード生成テンプレートをよりよく理解するために、次の例に従って記述し、生成されたクラスを表示します。
次のコードをファイル 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(){
}
}
上に描いた図をもとに、Dagger2 が生成したファイルを確認してみましょう。
- DaggerDemoComponent.java
- DemoAClass_Factory.java
- DemoBClass_Factory.java
- DemoBinds_Factory.java
- DemoInject_MembersInjector.java
- DemoSubComponent2_DemoModule2_GetProviderFactory.java
- DemoSubComponent2_DemoModule2_Proxy.java
次に、生成された 7 つのファイルを 1 つずつ確認して内容を確認し、残りの 6 つのクラスは DaggerDemoComponent.java で使用されます。したがって、最初に残りの 6 つのクラスを調べ、最後に DaggerDemoFactory.java を調べます。
DemoAClass_Factory、DemoBClass_Factory、DemoBinds_Factory
DemoAClass_Factory のソースコードは次のとおりです。
//对于任何类来讲,只要其构造函数带有@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 クラスの次のコードのため、補助メンバーの注入に使用されます。
class DemoInject{
@Inject
DemoAClass a;
}
補助クラス全体のソース コードは次のとおりです。
//每一个辅助注入的类,都是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 の実装ファクトリ クラスを表します。ソース コードは次のとおりです。
//对于任何一个被@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 は抽象モジュールを表現したもので、ソース コードは次のとおりです。
public final class DemoSubComponent2_DemoModule2_Proxy {
private DemoSubComponent2_DemoModule2_Proxy() {
}
public static DemoSubComponent2.DemoModule2 newInstance() {
return new DemoSubComponent2.DemoModule2();
}
}
DemoModule2 では、実装する必要があるものは何もなく、@Binds は意味的に十分に明白であるため、上記で生成されたクラスには余分なものはありません。より単純な
次に、DaggerDemoComponent が上で作成したクラスを使用してクラス間の依存関係を処理する方法を見てみましょう。
DaggerDemoコンポーネント
DaggerDemoComponent は依存関係注入全体への入り口であり、そのソース コードは次のとおりです。
//实现我们的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();
}
}
}
次の作業はコンポーネントで完了します。
- 実装されたコンポーネント、サブコンポーネント、およびそれらに対応する Builder クラスと Factory クラス。サブコンポーネントはコンポーネントの内部クラスです。
- 対応するインターフェイス メソッドを実装します。これらのメソッドは、他の xxx_Factory および xxxx_MembersInjector 補助クラスに委任されて完了します。
- 委任された xxx_Factory ファクトリ クラスと xxx_MembersInjector 補助クラスは正しく初期化されます。
この時点で、Dagger2 によって生成されたテンプレートを全体的に理解し、実装の詳細についていくつかのコメントを加えました。
次に、SystemUI の重要なコンポーネントの作成プロセスを見てみましょう。
SystemUI は Dagger2 の依存関係を作成するための開始点です
最初の記事では、SystemUIApplication.onCreate() の mContextAvailableCallback.onContextAvailable(this) について簡単に説明しました。
これは、Dagger2 が依存関係、つまり SystemUIAppComponentFactory.java での mContextAvailableCallback の割り当てを作成するための開始点です。
次のように:
@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 を呼び出して作成することがわかりました。名前から 1 つまたは 2 つ推測できます。構成から SystemUIFactory を作成します。
ああ、これは考えてみる価値がありますが、なぜ設定から作成するのでしょうか? 別の SytemUIFactory として構成できますか? SystemUIFactoryごとに違いはありますか?
質問しながら見てみよう
システムUIファクトリー
名前からすると、SystemUIFactory は SystemUI のファクトリ クラスのようです。前回の記事 Android 12 のソース コード分析 - アプリケーション層 2 (SystemUI の一般的な構成と起動プロセス): http://t.csdn.cn/AuzsLのカスタム コンポーネント セクションで、カスタム コンポーネントは SystemUI を継承しています。
SystemUIFactory はそのファクトリ クラスですか?
ソース コードを見てみましょう。干渉を減らすために、次のように、前のセクションの createFromConfig メソッドから始めます。
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);
}
}
次に、次のように初期化関数の入力を続けます。
@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() 関数では、次の 4 つの主な処理が行われます。
- GlobalRootComponentを作成して初期化する
- WMComponent を作成して初期化する
- SysUIComponentを作成して初期化する
- 依存関係の作成と初期化
これら 4 つのオブジェクトは SystemUI アプリケーション全体に必要なコンポーネントであり、これら 4 つのコンポーネントを通じて Dagger2 のさまざまな依存関係を取得できます。
これら 4 つのオブジェクトを 1 つずつ紹介する前に。まず、次のような以前の質問に対処しましょう。
- SystemUIFactory が構成から作成されるのはなぜですか?
- SystemUIFactory のネーミングは少し奇妙に感じますか?
質問 1 に回答してください: SystemUIFactory は SysetmUIFactory を直接インスタンス化できるだけでなく、SystemUIFactory のサブクラス (TvSystemUIFactory など) をインスタンス化する必要がある場合もあります。TvSystemUIFactory が必要な理由は、TvGloabRootComponent と呼ばれる GlobalRootComponent の別のバージョンが必要であるためです。そしてこの TvGlobalRootComponent GlobalRootComponentから継承
質問 2 に対する答え: SystemUIFactory によって提供されるインスタンス作成は、明らかに GloablRootComponentFactory と呼ばれる必要があります。SystemUIFactory と呼ぶべきではないのですが、これも開発者の厳密さが足りないところだと思います。
もちろん、私が理解していない他の意味もあるかもしれません。
この時点では、SystemUIFactory には実際に導入するものは何もありません。残りの内容はゲッターにすぎません。内容は単純なので、ここではスキップできます。
次に、いくつかのコンポーネントの作成プロセスです
グローバルルートコンポーネント
GlobalRootComponent の作成は、その図から始める必要があります。Android 12 のソース コード分析 - アプリケーション レイヤ 2 (SystemUI の一般的な構成と起動プロセス): http://t.csdn.cn/AuzsLの記事では、GlobalRootComponent のビルダー インターフェイスを定義しました。
次のように:
@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
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
内容は膨大ですが、実装は前に紹介したテンプレートとほぼ同じで、構造を理解するだけで済むため、分析を簡素化するためにコードの一部をインデントして実装の詳細を簡略化します。
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 インターフェイスの実装では、次の作業が完了します。
- Dagger2 のグラフに基づいて対応するコンストラクターを実装します。
- Dagger2 の図に従って、対応するインターフェイス メソッドを実装します。
- サブコンポーネントの場合は内部クラスとして実装します。
- 各ビルダーインターフェースを実装する
また、上記のことから、ボリュームが大幅に大きくなったことを除けば、本番環境とデモ テンプレートの間に大きな違いがないこともわかります。
次に、WMComponent の実装を見てみましょう。
WMコンポーネント
WMComponent は次のように定義されます
@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 には、ShellInit の戻り値を検索できる WMShellBaseModule も含まれています。次のように
WMShellBaseModule
WMShellBaseModuel は、次のように Dagger2 に ShellInit オブジェクトの作成方法を指示します。
@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 関連のコードの実装を見てみましょう。1 つ目はビルダーの実装です。
Dagger2 によって生成された WMComponent.Builder
GlobalRootComponent の以前の実装では、WMComponent.Builder の実装を確認しましたが、その内容は次のようになります。
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
GlobalRootComponent のサブコンポーネントとして、WMComponent は次のように DaggerGlobalRootComponent 内に配置されます。
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 が GlobalRootComponent とほぼ同じ構造を持つことがわかります。
これらの生成されたものは、現時点で関連付ける必要はなく、その構造と一般的な抽象コードだけを知っていればよく、実際のビジネス実装の詳細では、必要に応じて言及します。
もう一度注意してください: WMComponent は、Window Manager によって SystemUI に提供される対話型インターフェイスです。今、あなたはこの抽象的な意味を知るだけで十分です
次に、SysUIComponent を見ていきます。
SysUIコンポーネント
まず、ソース コードで SysUIComponent がどのように定義されているか、つまり、次のように SysUIComponent を描画する方法を確認してください。
@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 クラス内にあります。
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 関数の実装は非常に簡単です
- さまざまな Optional<T> など、必要な中間オブジェクトを保存します。
- newSysUIComponent インターフェイスの実装
次に、SysUIComponent の実装を見てみましょう。実は、SysUIComponent はすでによく知られており、その構造は GlbalRootComponent や WMComponent と同等です。
Dagger2 によって生成された SysUIComponent
GlobalRootComponent のサブコンポーネントとして、SysUIComponent の生成は次のように DaggerGlobalRootComponent 内にあります。
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 と非常によく似ていることがわかります。主な完了:
- 内部サブコンポーネントの Bulider の実装
- 内部サブコンポーネント ファクトリの実装
- 内部サブコンポーネントの実装
- 内部インターフェースメソッドの実装
上記の導入により、各コンポーネントの初期化プロセスと内部実装の詳細が基本的に非常に明確になりました。
次に、Dependency の実装の詳細が最後に 1 つ残っています。
依存
依存関係に対応する抽象化とは何ですか? 直接的な結論は次のとおりです。便宜上、Dagger2 の依存関係は各モジュールで直接参照できます。たとえば、SysUIComponent を通じて依存関係にアクセスしたい場合、次の呼び出し状況が発生する可能性があります。
d=sysuicomponent.getxxx().getxxx().getxxx().getxxx();
d.xxx();
上記のコードには getxxx() 関数の複数の層があるため、便宜上、Dependency を通じていくつかの一般的な依存関係を呼び出すことができます。現在提供されているメソッドは次のとおりです: 対応する依存関係を取得するためのDependency.get (dependency.class)
これがこのクラスの名前の由来でもあります。
上記の観点から、Dependency.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 は次の 2 つのことを行います。
- キャッシュは依存関係の Lazy<T> パッケージを使用する必要があります
- キャッシュに必要な依存関係の具体的なインスタンス。
- その後、必要に応じて、get() 関数を通じて対応する依存関係を取得できます。
ここまで、SystemUIFactory の init() メソッドにおける重要なコンポーネントの作成と初期化の詳細を紹介しました。SystemUI全体の起動も完了します。
起動プロセス全体は次のように要約されます。
- system_server が起動すると、さまざまなサービスが開始されます。
- 他のサービスを起動する場合は、まず PackageManager を通じて systemui を起動するコンポーネントの名前を取得し、その名前に従って systemui コンポーネントを起動します。
- 上記の手順で取得した名前は SystemUIService です。
- SystemUIService が開始されると、SystemUIApplication が最初に作成され、SystemUIAppComponentFactory が呼び出されて、作成前に対応する依存関係の注入が追加されます。
- SystemUIApplication が作成された後、SystemUIFactory.init() メソッドを呼び出して Dagger2 の依存関係が初期化されます。(この記事の内容)
- 同時に、システム起動ブロードキャストが SystemUIApplication で監視されます。
- 次に、SystemUIService を作成し、作成する前に SystemUIAppComponentFactory の対応するメソッドを呼び出して依存関係の注入を追加します。
- SystemUIService作成後、SystemUIApplication経由で各種サービスを起動します
次にSystemUIのUI部分に入ります。ステータス バーが画面全体にどのように追加されるかを確認してください。次に、ステップごとに分割して、ドロップダウン ステータス バーの各アイコンの実装を確認します。
最近授業に行かないといけないので、週に1回更新できるように頑張ります。