java - 如何在不强制消费应用程序使用 Dagger 的情况下构建基于 Dagger 的 Android 库?

标签 java android dagger-2 dagger

我正在开发一个 Android 库,它基本上是我编写的一些 REST 服务的客户端。我有几个存储类、网络队列、解析器等,并且像许多这样的类一样,它们依赖于 Context 或诸如 SharedPreferences 之类的东西,它们是从 上下文。这些对象都隐藏在外观类后面,因此我的库的使用者看不到它们或直接与它们交互。

为了我自己的理智,我想使用 Dagger 2 进行依赖注入(inject),以在我的库中内部管理这些类的实例。但是,我不想强​​制使用我的库的应用程序自己使用 Dagger;仅仅因为我选择使用 Dagger 并不意味着我的用户必须这样做。

我看到的所有教程似乎都期望我正在构建一个应用程序,而不仅仅是一个库。其中许多教程告诉我应该让我的 Application 类继承自 DaggerApplication。不过,就我而言,我的库中根本没有 Application(或任何 ActivityService 类),而且我不希望我的用户不得不使用 Dagger 的基类。

那么我怎样才能使用 Dagger 而不会将它“泄露”出我的库呢?我找到了部分答案 here ,但我不确定如何调整作者的“包装器”模式来处理我对 Context 的依赖。我可以只将上下文传递到包装器的 getComponent() 方法中,还是 Dagger 能够通过其他方式获取上下文引用?

最佳答案

几乎就像一个应用程序(当涉及到 Dagger 时)。是的,您没有 application 对象,但您并不真的需要一个。

作为您图书馆的消费者,我希望它易于使用,所以我根本不想知道 dagger 是什么(或者您是否在内部使用它)。

让您的用户在第一次调用您的图书馆时传递一个 Context(例如)。有一个 DaggerInjector(我认为您的示例将其称为包装器),它具有对您的 Component 接口(interface)的静态引用。

示例(因此,只是一个通用示例):

public class DaggerInjector {

    private static YourComponent component;

    private DaggerInjector() {
        super();
    }

    public static YourComponent getComponent() {
        return component;
    }

    public static YourComponent buildComponent(Context context) {
        component = DaggerYourComponent
                .builder()
                .yourModule(new YourModule(context))
                .build();
        return component;
    }
}

你的“模块”看起来像:

@Module
public class YourModule {

    private Context context;

    public YourModule(Context context) {
        this.context = context;
    }

    @Provides
    @Singleton
    final Context providesContext() {
        return context;
    }
}

使用方法:

让你的用户调用一个方法(或者如果组件为空,你第一次自己调用它):

DaggerInjector.buildComponent(context);

这将确保初始化 Dagger 组件并生成代码。了解调用 buildComponent 是一项昂贵的任务(Dagger 必须做很多事情!)所以只做一次(除非您需要使用仅在运行时已知的不同值重新初始化库)。

有些库只是在每次调用时都要求上下文,所以这不是不可能的;然后,您可以在第一次调用时初始化 Dagger(通过检查注入(inject)器中的 getComponent() 是否为 null)。

在您的 DaggerInjector.getComponent() 不再为 null 之后,您现在可以添加 @Inject 和适当的“可注入(inject)”内容......

例如:在 YourModule 中你可以:

@Provides
SomeObject providesSomeObject() {
    return new SomeObject();
}

// THIS “Context” here is automatically injected by Dagger thanks to the above.
@Provides
@Singleton
SomeOtherObject providesSomeOtherObject(Context context) {
    return new SomeOtherObject(context); //assume this one needs it
}

并且在任何“可注入(inject)”对象(即在您的组件中具有 inject 方法的对象……)您可以执行以下操作:

public class AnObjectThatWantsToInjectStuff {

    @Inject
    SomeObject someObject;
    @Inject 
    SomeOtherObject someOtherObject;

    public AnObjectThatWantsToInjectStuff() {
          super();
          DaggerInjector.getComponent().inject(this);

          // you can now use someObject and someOtherObject
    }
}

要使上述工作正常,您需要在 YourComponent(这是一个接口(interface))中编写如下代码:

无效注入(inject)(AnObjectThatWantsToInjectStuff 对象);

(否则调用 DaggerInjector.getComponent().inject(this) 将在编译时失败)

请注意,我从未将上下文传递给 YourInjectableContext,Dagger 已经知道如何获取它。

小心泄漏。对于所有/大多数情况,我建议您存储 context.getApplicationContext() 而不是简单的 Context (除非您明确需要 Activity 上下文来扩展布局/主题,消费应用程序提供的应用程序上下文就是您所需要的)。

关于java - 如何在不强制消费应用程序使用 Dagger 的情况下构建基于 Dagger 的 Android 库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45022696/

相关文章:

java - 游戏网络中合理的线程数

java - 带用户输入的 xsd 到 xml 工具

java - Netbeans Java 代码格式问题

android - OnePlus Espresso 测试运行问题 (Android Studio 3.6.2)

android - java.util.NoSuchElementException 导致找不到符号类 DataBindingComponent

java - Jtextarea出不来

java - 如何在 android 微调器下拉列表中搜索

java - Android Studio 其他Activity打不开

java - 使用Kotlin创建自定义Dagger 2示波器

kotlin - 如何使用 Dagger 2 注入(inject) Kotlin 委托(delegate)属性?