AAC学习笔记Dagger(二)--Activity注入之前

本文为《Android Architecture Components学习笔记》的一部分
文档代码为Kotlin,但是系统生成的代码仍然为Java
为了方便理解,我将官方示例做了逐步拆解
本人水平有限,如有不当之处请不吝赐教


上一篇分析了Dagger的基本使用方法,还是很弱爆的。在项目里如何应用呢,本篇捋一下Activity对象注入的那些事。


Application

说明一下GithubApp这个类,在AndroidManifest里:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ……
    <application
        android:name=".GithubApp"
        ……

android:name属性是用来设置所有activity属于哪个application的
GithubApp这个类放的是全局成员,代码中的AppInjector.init(this)在activity之前执行
AppInjector.init(this)也是所有注入的开始。

第一步,跟上篇一样先看注入者GithubApp

//需要实现HasActivityInjector
class GithubApp : Application(), HasActivityInjector {
    @Inject
    lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
    
    override fun onCreate() {
       ……
       //重写了onCreate(),此句是重点
       AppInjector.init(this)
    }
    override fun activityInjector() = dispatchingAndroidInjector
}

第二步,Component:

@Component(modules = [AndroidInjectionModule::class])
interface AppComponent {
    //此处声明了Builder
    @Component.Builder
    interface Builder {
        @BindsInstance
        fun application(application: Application): Builder
        fun build(): AppComponent
    }
    fun inject(githubApp: GithubApp)
}

build后GithubApp_MembersInjectorDaggerAppComponent就出来了
GithubApp 是Application,所以这里实现了HasActivityInjector,从而能够实现Activity的注入
这里还有一个很重要的类:DispatchingAndroidInjector。后面会详细说

AppInjector(一)

object AppInjector {
    fun init(githubApp: GithubApp) {
        //第一句:完成对githubApp的注入
        DaggerAppComponent.builder().application(githubApp).build().inject(githubApp)
        //第二句:override onActivityCreated,加入handleActivity
        githubApp.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
                override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {handleActivity(activity)}
        })
    }
    private fun handleActivity(activity: Activity)  {...}//为了好看,这里先收起来
}

先看AppInjector.init第一句:

    DaggerAppComponent.builder()//通过此静态方法得到Builder
 	                  .application(githubApp)//包含githubApp的Builder
 			          .build()//得到DaggerAppComponent对象
 			          .inject(githubApp)

这里用到的DaggerAppComponent几个方法:

public final class DaggerAppComponent implements AppComponent {
  private DaggerAppComponent(Builder builder) {}

  public static AppComponent.Builder builder() { return new Builder();}

  private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
    //此处返回了一个空Map的DispatchingAndroidInjector
    return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(        
        Collections.<~> emptyMap());
  }

  //将DispatchingAndroidInjector注入到githubApp.dispatchingAndroidInjector
  @Override
  public void inject(GithubApp githubApp) {injectGithubApp(githubApp);}

  private GithubApp injectGithubApp(GithubApp instance) {
    GithubApp_MembersInjector.injectDispatchingAndroidInjector(instance, getDispatchingAndroidInjectorOfActivity());
    return instance;
  }

  //此处实现的 AppComponent.Builder,就是前面写在Component里的
  //重写的application、build是我们自己定义的
  private static final class Builder implements AppComponent.Builder {
    private Application application;

    @Override
    public AppComponent build() {return new DaggerAppComponent(this);}

    @Override
    public Builder application(Application application) {
      this.application = Preconditions.checkNotNull(application);
      return this;
    }
  }
}

代码雪薇有点复杂,这里只需要记住两点:
1、AppInjector.init第一句完成了githubApp.dispatchingAndroidInjector注入
2、通过GithubApp_MembersInjector实现。(代码不难,上篇都叨叨过)

这里出现了DispatchingAndroidInjector在继续AppInjector.init第二句前,先看看它吧

DispatchingAndroidInjector

先看DispatchingAndroidInjector

/*
 * 对核心Android类型的实例(Activity、Fragment……)执行注入,它是由Android框架而不是Dagger实现的
 * 实现了AndroidInjector,具体类可通过AndroidInjector.Factory注入依赖类
 * 通过在实例上调用Object#getClass(),就可以得到它的AndroidInjector.Factory
 */
@Beta
public final class DispatchingAndroidInjector<T> implements AndroidInjector<T> {
  /*注入Factory的Map类型,下面代码为了方便看Map类型都省略了
  *这个Map中K就是Class,V是AndroidInjector.Factory
  */
  private final Map<Class<? extends T>, Provider<AndroidInjector.Factory<? extends T>>> injectorFactories;

  @Inject
  DispatchingAndroidInjector(Map<~> injectorFactories) {
  	this.injectorFactories = injectorFactories;
  }

  //尝试在 {instance}上注入, 返回是否成功
  @CanIgnoreReturnValue
  //能否在Map中获取factory
  public boolean maybeInject(T instance) {
    Provider<AndroidInjector.Factory<? extends T>> factoryProvider =
        injectorFactories.get(instance.getClass());
    if (factoryProvider == null) {return false;}

    @SuppressWarnings("unchecked")
    AndroidInjector.Factory<T> factory = (AndroidInjector.Factory<T>) factoryProvider.get();
    //转型后执行注入
    try {
      AndroidInjector<T> injector =checkNotNull(factory.create(instance),, );

      injector.inject(instance);
      return true;
    } catch (ClassCastException e) {}
  }

  //对{instance}执行成员注入
  @Override
  public void inject(T instance) {
    boolean wasInjected = maybeInject(instance);
  }
}

通过看DispatchingAndroidInjector核心代码,它主要通过:
AndroidInjector.create()AndroidInjector.inject()完成注入。

到这里了会有些凌乱,记住DispatchingAndroidInjector以及AppInjector到后面就会清晰了

Activity注入

我们来完成MainActivity加入DispatchingAndroidInjector(我是将示例代码逐步完成的)
这时的MainActivity是这个样子:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)
    }
}

还是一般规律,Module:

@Suppress("unused")
@Module
abstract class MainActivityModule {
    @ContributesAndroidInjector
    abstract fun contributeMainActivity(): MainActivity
}

OK,build一下看DaggerAppComponent

public final class DaggerAppComponent implements AppComponent {
  //MainActivity的Provider
  private Provider<MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.Builder>
      mainActivitySubcomponentBuilderProvider;

  //构造函数,执行初始化
  private DaggerAppComponent(Builder builder) {initialize(builder);}
  private void initialize(final Builder builder) {
    //初始化MainActivity的Provider
    this.mainActivitySubcomponentBuilderProvider =
        new Provider<MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.Builder>() {
          @Override
          public MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.Builder get() {
            return new MainActivitySubcomponentBuilder();
          }
        };
  }
  public static AppComponent.Builder builder() {return new Builder();}

  //得到包含MainActivity的Map
  private Map<~> getMapOfClassOfAndProviderOfFactoryOf() {
    return Collections.<~>
    	 singletonMap(MainActivity.class, (Provider) mainActivitySubcomponentBuilderProvider);
  }

  //创建并返回含MainActivity的Map的DispatchingAndroidInjector对象
  private DispatchingAndroidInjector<Activity> getDispatchingAndroidInjectorOfActivity() {
    return DispatchingAndroidInjector_Factory.newDispatchingAndroidInjector(
        getMapOfClassOfAndProviderOfFactoryOf());
  }


  //执行注入
  @Override
  public void inject(GithubApp githubApp) {injectGithubApp(githubApp);}
  private GithubApp injectGithubApp(GithubApp instance) {
    GithubApp_MembersInjector.injectDispatchingAndroidInjector(
        instance, getDispatchingAndroidInjectorOfActivity());
    return instance;
  }

  //此处代码略,前面分析过
  private static final class Builder implements AppComponent.Builder {...}

  private final class MainActivitySubcomponentBuilder
      extends MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.Builder {
    private MainActivity seedInstance;

    @Override//此处重写的是AndroidInjector.Builder.build()
    public MainActivityModule_ContributeMainActivity.MainActivitySubcomponent build() {
      if (seedInstance == null) {
        throw new IllegalStateException(MainActivity.class.getCanonicalName() + " must be set");
      }
      return new MainActivitySubcomponentImpl(this);
    }

    @Override//此处重写的是AndroidInjector.Builder.seedInstance()
    public void seedInstance(MainActivity arg0) {
      this.seedInstance = Preconditions.checkNotNull(arg0);
    }
  }

  private final class MainActivitySubcomponentImpl
      implements MainActivityModule_ContributeMainActivity.MainActivitySubcomponent {
    private MainActivitySubcomponentImpl(MainActivitySubcomponentBuilder builder) {}

    @Override//此处是AndroidInjector.inject()
    public void inject(MainActivity arg0) {}
  }
}

代码较多,简单来说就是通过DispatchingAndroidInjector完成了MainActivity的注入。

再加一个Activity

得先有个Activity,就叫Activity2吧
在Module里添加:

@Suppress("unused")
@Module
abstract class MainActivityModule {
    @ContributesAndroidInjector
    abstract fun contributeMainActivity(): MainActivity
    @ContributesAndroidInjector
    abstract fun contributeActivity2(): Activity2
}

build后,再看DaggerAppComponent

public final class DaggerAppComponent implements AppComponent {
  private Provider<MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.Builder>
      mainActivitySubcomponentBuilderProvider;

  //多了Activity2
  private Provider<MainActivityModule_ContributeActivity2.Activity2Subcomponent.Builder>
      activity2SubcomponentBuilderProvider;

  //成了这样子,Map里加入了两个
  private Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
      getMapOfClassOfAndProviderOfFactoryOf() {
    return MapBuilder
        .<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>
            newMapBuilder(2)
        .put(MainActivity.class, (Provider) mainActivitySubcomponentBuilderProvider)
        .put(Activity2.class, (Provider) activity2SubcomponentBuilderProvider)
        .build();
  }

  //这里也是两套
  private void initialize(final Builder builder) {
    this.mainActivitySubcomponentBuilderProvider =...
    this.activity2SubcomponentBuilderProvider =...
  }

   private final class MainActivitySubcomponentBuilder
      extends MainActivityModule_ContributeMainActivity.MainActivitySubcomponent.Builder {...}
   
  private final class MainActivitySubcomponentImpl
      implements MainActivityModule_ContributeMainActivity.MainActivitySubcomponent {...}

  private final class Activity2SubcomponentBuilder
      extends MainActivityModule_ContributeActivity2.Activity2Subcomponent.Builder {...}

  private final class Activity2SubcomponentImpl
      implements MainActivityModule_ContributeActivity2.Activity2Subcomponent {...}
}

都double了……

总结一下

  • 实际项目里注入Activity,只是修改Module即可。简单的不要不要的。
  • 通过看源码,更能理解构建者、工厂模式的应用,同时针对Map的三种实现方法有所了解
  • 为什么要注入Activity呢,继续往下就会发现这样做的好处。

猜你喜欢

转载自blog.csdn.net/jouter/article/details/83309057