简体   繁体   English

Dagger 2 在 Application 类中构建组件的良好实践

[英]Dagger 2 Good practices to build components in Application class

I know probably there is no clear answer for this question.我知道这个问题可能没有明确的答案。

But I would like to know Your opinions and maybe new ideas.但我想知道你的意见,也许还有新的想法。

I'm wondering which of the following options is the best/right/correct way to build the app-level Dagger Component in Application class.我想知道以下哪个选项是在 Application 类中构建应用程序级 Dagger 组件的最佳/正确/正确方法。


Example 1:示例 1:

public class MyApp extends Application {

    private NetComponent mNetComponent;

    @Override
    public void onCreate() {
        super.onCreate();

        mNetComponent = DaggerNetComponent.builder()
                .appModule(new AppModule(this)) 
                .netModule(new NetModule("https://api.github.com"))
                .build();
    }

    public NetComponent getNetComponent() {
        return mNetComponent;
    }
}

Usage:用法:

((MyApp) getApplication()).getNetComponent().inject(this);

Example 2:示例 2:

 class MyApplication extends Application {

    private static MyComponent component;

    @Override
    void onCreate() {
        component = DaggerMyComponent.builder()
                .contextModule(new ContextModule(getApplicationContext()))
                .build();
    }

    public static MyComponent getMyComponent() {
        return component;
    }
}

Usage:用法:

MyApplication.getMyComponent().inject(this)

Example 3:示例 3:

class CustomApplication: Application() {
    lateinit var component: SingletonComponent
        private set

    override fun onCreate() {
        super.onCreate()
        INSTANCE = this
        component = DaggerSingletonComponent.builder()
                       .contextModule(ContextModule(this))
                       .build()
    }

    companion object {
       private var INSTANCE: CustomApplication? = null

       @JvmStatic
       fun get(): CustomApplication = INSTANCE!!

    }
}

Then:然后:

class Injector private constructor() {
    companion object {
        @JvmStatic
        fun get() : SingletonComponent = CustomApplication.get().component
    }
}

Usage:用法:

Injector.get().catRepository()

Example 4:示例 4:

 class App : Application() {

    var repositoryComponent: RepositoryComponent? = null
    var appComponent: AppComponent? = null

    override fun onCreate() {
        super.onCreate()
        instance = this
        appComponent = DaggerAppComponent.builder().application(this).build()
        repositoryComponent = DaggerRepositoryComponent.builder().build()
    }

    companion object {

        private var instance: App? = null

        fun get(): App {
            return instance!!
        }
    }
}

Usage:用法:

 App.get().repositoryComponent!!.inject(this)

What do you think about this?你怎么看待这件事? Is there any better / cleaner way to do this?有没有更好/更清洁的方法来做到这一点? Maybe provided examples are fine?也许提供的例子很好? Or maybe just one of them?或者也许只是其中之一?

I will be grateful for any good examples / tips / advices.我将不胜感激任何好的例子/提示/建议。

Thanks!谢谢!

Okay, no one answered in 5 days so it's my turn, despite my bias :p好的,5 天内没有人回答所以轮到我了,尽管我有偏见:p

  • Option #1选项1

((MyApp) getApplication()).getNetComponent().inject(this);

It's an "ok" version of doing things, except for two things.这是做事的“确定”版本,除了两件事。

First, the name.首先,名称。 NetComponent isn't really for networking, it's the app-global singleton component, so it should be either called SingletonComponent or AppComponent . NetComponent并不是真正用于网络,它是应用程序全局的单例组件,所以它应该被称为SingletonComponentAppComponent But naming it NetComponent is disingenuous, it's typically responsible for everything else too.但是将它命名为NetComponent是不诚实的,它通常也负责其他所有事情

Second problem is that you need a reference to Context to access your dependency graph, making Context actually be a dependency rather than it being provided to you.第二个问题是你需要一个对Context的引用来访问你的依赖关系图,使得Context实际上是一个依赖项而不是它被提供给你。

  • Option #2选项#2

MyApplication.getMyComponent().inject(this)

This is a perfectly fine way of doing things, but you need to know that to reach your object graph, you need to access the static method of MyApplication .这是一种非常好的做事方式,但您需要知道要访问您的对象图,您需要访问MyApplication的静态方法。

  • Option #3选项#3

Injector.get().inject(this)

Internally, this solution actually just calls over to get the app component, public static AppComponent get() { return MyApplication.getInstance().getComponent(); }在内部,这个解决方案实际上只是调用获取应用组件, public static AppComponent get() { return MyApplication.getInstance().getComponent(); } public static AppComponent get() { return MyApplication.getInstance().getComponent(); }

The benefit is that getComponent() is exposed via an instance method of Application, so it could be theoretically swapped out.好处是getComponent()通过 Application 的实例方法公开,因此理论上可以将其换出。

Also, invoking a method on something called Injector.get() is more obviously an "injector" than, well, an application class.此外,在称为Injector.get()东西上调用方法更明显是“注入器”,而不是应用程序类。

As for whether you use .catRepository() or .inject(this) , it's up to you;至于你使用.catRepository()还是.inject(this) ,这取决于你; but I personally prefer calling the provision methods to get the deps in Activity/Fragment, because listing the member-injection targets adds a lot of clutter to the component over time.但我个人更喜欢调用配置方法来获取 Activity/Fragment 中的 deps,因为随着时间的推移,列出成员注入目标会给组件增加很多混乱。

4.) 4.)

App.get().repositoryComponent!!.inject(this)

You can ditch the !!你可以放弃!! if repositoryComponent is a lateinit var .如果repositoryComponent是一个lateinit var

Having two components for the same scope (and therefore two different object graphs) will only cause trouble, out of all of the options, this is the worst.具有相同范围的两个组件(因此有两个不同的对象图)只会导致麻烦,在所有选项中,这是最糟糕的。


In my opinion, the 3rd option is the best.在我看来,第三个选项是最好的。 Technically it's the same as option #2 with an additional "indirection" through the instance method of Application that actually returns the component.从技术上讲,它与选项 #2 相同,但通过实际返回组件的 Application 的实例方法增加了一个“间接”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM