从源码剖析Dagger2:Component和Module入门

本文深入剖析Dagger2在Android项目中的应用,通过源码分析DaggerMainComponent、MainViewModel_Factory、MainActivity_MembersInjector和MainModule_ProvideSharedPreferencesFactory的生成与功能,帮助开发者理解Dagger的依赖注入机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

稍微复杂一点的安卓应用基本上都采用了Dagger。但是,很多工程师在学习Dagger的过程中,都抱怨学习曲线很陡峭,上手不容易。究其原因,主要是因为Dagger在编译阶段自动生成了很多代码。而通常情况下,工程师是不会阅读或者理解这些代码的。这就导致了许多安卓工程师只会机械地照搬Dagger的示例教程,而不能从原理上深入理解Dagger的实现。因此,在很多项目中,Dagger无法发挥出它的全部优势,有时甚至会被用错。

为了解决上述问题,我们尝试对Dagger进行源码级别的剖析,以此加深对Dagger的理解。

项目概览

本文将基于一个叫DaggerBasic的项目进行源码分析。这个项目包含了MainActivity、MainViewModel、MainComponent和MainModule。各个类之间的关系图如下所示。
在这里插入图片描述
经过编译之后,Dagger会自动生成如下类文件:

  • DaggerMainComponent:MainComponent的实现类,提供MainActivity所需的依赖对象。
  • MainViewModel_Factory:MainViewModel的工厂类,负责创建MainViewModel。
  • MainActivity_MembersInjector:负责向MainActivity注入依赖对象的类。
  • MainModule_ProvideSharedPreferencesFactory:负责提供SharedPreferences的工厂类。

接下来我们就逐个分析一下上述生成的类及其功能。

DaggerMainComponent

MainComponent是MainActivity对应的依赖关系图,所有MainActivity依赖的对象,都可以通过MainComponent获得。为了让Dagger能够提供这些对象,开发者需要创建一个接口,并使用 @Component为其添加注释。而Dagger则会自动为我们生成这个接口的实现。

MainComponent的代码如下所示。

@Component(modules = [MainModule::class])
interface MainComponent {

    fun inject(activity: MainActivity)

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance context: Context): MainComponent
    }
}

而DaggerMainComponent则是MainComponent的实现类,代码如下所示。

public final class DaggerMainComponent implements MainComponent {
  private final Context context;
  private final MainModule mainModule;

  private DaggerMainComponent(MainModule mainModuleParam, Context contextParam) {
    this.context = contextParam;
    this.mainModule = mainModuleParam;
  }

  public static MainComponent.Factory factory() {
    return new Factory();
  }

  private SharedPreferences getSharedPreferences() {
    return MainModule_ProvideSharedPreferencesFactory.provideSharedPreferences(mainModule, context);
  }

  private MainViewModel getMainViewModel() {
    return new MainViewModel(getSharedPreferences());
  }

  @Override
  public void inject(MainActivity activity) {
    injectMainActivity(activity);
  }

  private MainActivity injectMainActivity(MainActivity instance) {
    MainActivity_MembersInjector.injectMainViewModel(instance, getMainViewModel());
    return instance;
  }

  private static final class Factory implements MainComponent.Factory {
    @Override
    public MainComponent create(Context context) {
      Preconditions.checkNotNull(context);
      return new DaggerMainComponent(new MainModule(), context);
    }
  }
}

可以看到,DaggerMainComponent最重要的职责就是提供MainViewModel和SharedPreferences两个依赖对象。对于MainViewModel,DaggerMainComponent总是创建新的对象实例(我们会在讲解Scope的时候详细描述如何对这个行为进行优化)。对于SharedPreferences,DaggerMainComponent则是利用MainModule_ProvideSharedPreferencesFactory来创建SharedPreferences对象实例。

同时,DaggerMainComponent实现了inject方法。该方法接收一个MainActivity实例,并将MainActivity需要的依赖对象赋值给它,从而完成依赖注入。

最后,DaggerMainComponent还提供了MainComponent.Factory的实现,它被用来创建DaggerMainComponent的对象实例。

MainViewModel_Factory

MainViewModel_Factory是MainViewModel的工厂类,负责创建MainViewModel的实例。在这个例子中,由于我们没有为MainViewModel定义Scope,因此DaggerMainComponent总是直接调用MainViewModel的构造方法创建新的MainViewModel实例。我们将在后续的例子中展示MainViewModel_Factory的功能。

MainViewModel的代码如下所示。

class MainViewModel @Inject constructor(sharedPreferences: SharedPreferences)

MainViewModel_Factory的源代码如下所示。

public final class MainViewModel_Factory implements Factory<MainViewModel> {
  private final Provider<SharedPreferences> sharedPreferencesProvider;

  public MainViewModel_Factory(Provider<SharedPreferences> sharedPreferencesProvider) {
    this.sharedPreferencesProvider = sharedPreferencesProvider;
  }

  @Override
  public MainViewModel get() {
    return new MainViewModel(sharedPreferencesProvider.get());
  }

  public static MainViewModel_Factory create(
      Provider<SharedPreferences> sharedPreferencesProvider) {
    return new MainViewModel_Factory(sharedPreferencesProvider);
  }

  public static MainViewModel newInstance(SharedPreferences sharedPreferences) {
    return new MainViewModel(sharedPreferences);
  }
}

MainActivity_MembersInjector

MainActivity_MembersInjector接收MainActivity实例并负责向它注入依赖对象。Dagger会为每一个需要注入依赖对象的Activity生成一个MembersInjector。MainActivity_MembersInjector在DaggerMainComponent的injectMainActivity被调用。

MainActivity的代码如下所示。

class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var mainViewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        DaggerMainComponent.factory().create(applicationContext).inject(this)

        super.onCreate(savedInstanceState)
    }
}

MainActivity_MembersInjector的源代码如下。

public final class MainActivity_MembersInjector implements MembersInjector<MainActivity> {
  private final Provider<MainViewModel> mainViewModelProvider;

  public MainActivity_MembersInjector(Provider<MainViewModel> mainViewModelProvider) {
    this.mainViewModelProvider = mainViewModelProvider;
  }

  public static MembersInjector<MainActivity> create(
      Provider<MainViewModel> mainViewModelProvider) {
    return new MainActivity_MembersInjector(mainViewModelProvider);
  }

  @Override
  public void injectMembers(MainActivity instance) {
    injectMainViewModel(instance, mainViewModelProvider.get());
  }

  public static void injectMainViewModel(MainActivity instance, MainViewModel mainViewModel) {
    instance.mainViewModel = mainViewModel;
  }
}

可以看到,在injectMainViewModel方法中,MainActivity_MembersInjector将MainViewModel的实例赋给了MainActivity对于的成员变量,从而完成了依赖注入。

MainModule_ProvideSharedPreferencesFactory

MainModule的代码如下所示。

@Module
class MainModule {

    @Provides
    fun provideSharedPreferences(appContext: Context): SharedPreferences {
        return appContext.getSharedPreferences("SharedPreferences", MODE_PRIVATE)
    }
}

针对Module中每一个被标记为@Provides的方法,Dagger会生成一个工厂类,用来提供对应的依赖对象。在这个例子中,Dagger为provideSharedPreferences生成了MainModule_ProvideSharedPreferencesFactory类,它可以提供SharedPreferences的实例,其源代码如下:

public final class MainModule_ProvideSharedPreferencesFactory
    implements Factory<SharedPreferences> {
  private final MainModule module;

  private final Provider<Context> appContextProvider;

  public MainModule_ProvideSharedPreferencesFactory(
      MainModule module, Provider<Context> appContextProvider) {
    this.module = module;
    this.appContextProvider = appContextProvider;
  }

  @Override
  public SharedPreferences get() {
    return provideSharedPreferences(module, appContextProvider.get());
  }

  public static MainModule_ProvideSharedPreferencesFactory create(
      MainModule module, Provider<Context> appContextProvider) {
    return new MainModule_ProvideSharedPreferencesFactory(module, appContextProvider);
  }

  public static SharedPreferences provideSharedPreferences(
      MainModule instance, Context appContext) {
    return Preconditions.checkNotNull(
        instance.provideSharedPreferences(appContext),
        "Cannot return null from a non-@Nullable @Provides method");
  }
}

总结

通过上述分析,我们可以通过下面这张图来展示Dagger生成的类及其对应关系。
在这里插入图片描述
左边的类是开发者定义的接口或者类,右边的类是Dagger生成的类。二者的桥梁就是Dagger注解。通过上述分析,我们就很好理解为什么在MainActivity的onCreate方法中,我们要插入如下代码了。

DaggerMainComponent.factory().create(applicationContext).inject(this)

其实这行代码就是创建DaggerMainComponent,生成MainActivity需要的依赖对象图,然后将依赖对象注入到MainActivity中。

至此,我们从源码级别对Dagger进行了基本的分析,展示了Component和Module是如何工作的。读者可以发现,其实Dagger并没有那么神秘,它只不过按照最优的方式为我们生成了一些模板方法,节约了开发者的时间而已。在后续的文章中,我们还将从源码级别分析其他Dagger的高级特性,欢迎关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值