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

这篇具有很好参考价值的文章主要介绍了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的文件中

//最顶层的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的源码如下:

//对于任何类来讲,只要其构造函数带有@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如何使用上面创建的类来处理他们之间的依赖关系

DaggerDemoComponent

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

在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中。

如下:

@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方法开始查看,如下

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()函数中,主要做了四件事:

  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接口。

如下:

@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接口的实现中,分别完成了如下的工作:

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

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

接下来看看WMComponent的实现

WMComponent

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的还包含一个WMShellBaseModule在其中可以搜寻到ShellInit的返回。如下

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相关代码的实现。首先是其Builder的实现

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

WMComponent作为GlobalRootComponent的subcomponent,则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这个subcomponent 几乎和GlobalRootComponent的结构一致。

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

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

接下来继续看看SysUIComponent.

SysUIComponent

先看看源码中,是如何定义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函数的实现很是简单

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

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

Dagger2生成的SysUIComponent

作为GlobalRootComponent的subcomponent,所以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很是类似。主要完成:

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

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

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

Dependency

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

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

上面的代码中,出现了多层的getxxx()函数,因此,为了方便,将一些常见的依赖,通过Dependency来调用即可。现在提供的方法为:Dependency.get(依赖.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就做了两件事情:

  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部分。看看状态栏是如何被加入整个屏幕的。然后一步步拆分,查看下拉状态栏中的各个图标的实现

因为最近要上课,尽量保持一周一更文章来源地址https://www.toymoban.com/news/detail-682174.html

到了这里,关于Android 12 源码分析 —— 应用层 三(SystemUIFactory及其Dependency解析)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 应用层 到 HAL 层

    如下 AOSP软件堆栈架构图 主要跨两个阶段 Android Apps == Android Framework == HAL ,这种 IPC跨进程通信 在 Android 中必须要了解的相关知识点: 1》 Binder IPC 通信机制;2》 JNI 调用;3》 AIDL、HIDL 接口定义语言 1》 Binder IPC 通信机制 IPC 域 说明 /dev/binder 框架/应用进程之间的 IPC,使用

    2024年02月10日
    浏览(41)
  • 4.1 应用层Hook挂钩原理分析

    InlineHook 是一种计算机安全编程技术,其原理是在计算机程序执行期间进行拦截、修改、增强现有函数功能。它使用钩子函数(也可以称为回调函数)来截获程序执行的各种事件,并在事件发生前或后进行自定义处理,从而控制或增强程序行为。Hook技术常被用于系统加速、功

    2024年02月08日
    浏览(43)
  • 《计算机网络》实验八 应用层相关协议分析

    实验八 应用层相关协议分析.............................................................................................. 2 一、实验目的.................................................................................................................... 2 二、实验原理.......................................................................

    2024年02月03日
    浏览(52)
  • 根据源码,模拟实现 RabbitMQ - 网络通讯设计,自定义应用层协议,实现 BrokerServer (8)

    目录 一、网络通讯协议设计 1.1、交互模型 1.2、自定义应用层协议 1.2.1、请求和响应格式约定 ​编辑 1.2.2、参数说明 1.2.3、具体例子 1.2.4、特殊栗子 1.3、实现 BrokerServer 1.3.1、属性和构造 1.3.2、启动 BrokerServer 1.3.3、停止 BrokerServer 1.3.4、处理每一个客户端连接 1.3.5、读取请求

    2024年02月10日
    浏览(51)
  • 【音视频|ALSA】基于alsa-lib开发ALSA应用层程序--附带源码

    😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭 🤣本文内容🤣:🍭基于alsa-lib开发ALSA应用层程序🍭 😎金句分享😎:🍭盖士人读书,第一要有志,第二要有识,第三要有恒。有志则断不甘为下流,有

    2024年02月08日
    浏览(73)
  • 【计算机网络概述】第二章:应用层:2.1 应用层原理

    客户端/服务器模式 peer to peer 模式(对等模式)        在第一章的内容中,我们学习了计算机网络的大体轮廓,因为在计算机网络中,我们需要记住非常多的专有名词,所以在第一章中,我们需要进行非常多的记忆。第一章还是非常重要的。        比如,我们所使用

    2024年01月18日
    浏览(56)
  • 【网络】-- 应用层

    目录 TCP协议通讯流程 三次握手的过程 四次挥手的过程 TCP 和 UDP 对比 应用层 \\\"协议\\\" 网络版计算器 认识TCP 守护进程 铺垫讲解 守护进程讲解 setsid 总结         下图是基于TCP 协议的客户端 / 服务器程序的一般流程: TCP是面向连接的通讯协议,在通讯之前,需要进行 3次握

    2023年04月09日
    浏览(61)
  • 应用层与传输层~

    应用层是负责应用程序之间沟通的一层。由于不同的网络应用的应用进程之间,有着不同的通信规则,因此自然就需要应用层协议来解决这些问题,这就构成了应用层的主要内容即:精确定义这些通信规则。 应用层有不少应用广泛的协议,像域名系统(DNS)、文件传输协议(

    2023年04月08日
    浏览(43)
  • 第6章:应用层

    2023年09月10日
    浏览(42)
  • 应用层协议 HTTP

    我们已经学过 TCP/IP , 已然知道数据能从客户端进程经过路径选择跨网络传送到服务器端进程。 我们还需要知道的是,我们把数据从 A 端传送到 B 端, TCP/IP 解决的是顺丰的功能,而两端还要对数据进行加工处理或者使用,所以我们还需要一层协议,不关心通信细节,关心应用

    2024年02月06日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包