安卓Dagger 2:POJO字段注射为空

6

我今天刚开始使用Dagger 2,对如何设置一切感到有些困惑。

我试图注入一个POJO,但它始终为空。 首先是一些代码:

App.java

private AppComponent appComponent;

@Override
public void onCreate() {
    super.onCreate();
    appComponent = DaggerAppComponent
            .builder()
            .appModule(new AppModule(this))
            .build();
}

public AppComponent component() {
    return appComponent;
}

AppModule.java

@Module
public class AppModule {
    private Application app;

    public AppModule(Application app) {
        this.app = app;
    }

    @Provides @Singleton
    public Application application() {
        return app;
    }
}

AppComponent.java

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    void inject(App application);
    Application application();
}

NetworkingManager.java

@Singleton
public class NetworkingManager {
    private Context ctx;

    @Inject
    public NetworkingManager(Context context) {
        this.ctx = context;
    }
}

NetModule.java

@Module
public class NetModule {
    @Provides @Singleton
    public NetworkingManager provideNetworkingManager(Application application) {
        return new NetworkingManager(application);
    }
}

NetComponent.java

@Singleton
@Component(modules = {NetModule.class},
        dependencies = {AppModule.class})
public interface NetComponent {
    void inject(NetworkingManager networkingManager);
}

SomeClass.java

@Inject
NetworkingManager networkingManager;

public void doSomethingWithNetworkManager() {
    networkManager.doStuff();
}

我花了很多时间查看了许多教程、Stack Overflow问题和示例,但是我还没有找出我做错了什么。

我99%确定我设置有误,但是我还没有找出是什么问题。


看起来你有点困惑。你的目标是什么?你在哪里尝试使用“NetworkingManager”? - Emmanuel
NetworkManager目前是一个单例。它处理所有异步网络操作。它被广泛使用。我的目标是消除单例并切换到DI,同时使该类可测试。 - Jordan
1个回答

10

根据您的评论,您希望在应用程序的任何地方都可以使用 NetworkingManager

让我们从您对 Component 的定义开始:

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    void inject(App application);
}

这告诉Dagger该组件将注入App类。现在,在这里,您还可以告诉Dagger您想要注入的其他类。因此,如果您想注入一个Activity,例如,您需要添加:

这告诉Dagger该组件将注入App类。现在,在这里,您还可以告诉Dagger您想要注入的其他类。因此,如果您想注入一个Activity,例如,您需要添加:

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
    void inject(App application);
    void inject(MainActivity activity) //Where MainActivity is a class that extends Activity.
}

请注意,这不是在我看来共享应用程序范围依赖项的最佳方法;你应该创建一个从AppComponent继承的Component,并使AppComponent公开所需的共享依赖项。

现在让我们看看你的模块类:

@Module
public class NetModule {
    @Provides @Singleton
    public NetworkingManager provideNetworkingManager(Application application) {
        return new NetworkingManager(application);
    }
}

你提供了一个NetworkingManager,这很好。你的NetworkingManager需要一个Application(实际上是一个Context),为什么不在NetworkingManager内部提供App呢?或者更好的方法是,为什么不在AppModule内提供NetworkingManager,因为AppModule应该提供整个Application通用的东西:

@Module
public class AppModule {
    private Application app;

    public AppModule(Application app) {
        this.app = app;
    }

    @Provides @Singleton
    public Application application() {
        return app;
    }

    @Provides @Singleton
    public NetworkingManager provideNetworkingManager(Application application) {
        return new NetworkingManager(application);
    }
}

现在在你的App类内部:
public class App extends Application {
    private AppComponent appComponent;

@Override
public void onCreate() {
    super.onCreate();
    appComponent = DaggerAppComponent
            .builder()
            .appModule(new AppModule(this))
            .build();
   appComponent.inject(this);
}

public AppComponent component() {
    return appComponent;
 }
}

在我们的假想MainActivity中:

public class MainActivity extends Activity {

private AppComponent appComponent;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    appComponent = ((App)getApplicationContext()).getAppComponent();
    appComponent.inject(this);
   }
 }

看起来您没有正确使用@Component(dependencies = {...})。 当您想要使用上述机制将一个组件的依赖项暴露给另一个组件时,dependencies会派上用场。


好的,这样有点更清楚了。1)我假设在App.onCreate()中你指的是.build()而不是.inject(this),因为inject()返回void。2)NetworkingManager在与App不同的包中。我在考虑是否最好为每个包保持单独的模块。这不可能吗?3)在 MainActivity.onCreate() 中获取AppComponent对于活动和片段是可以的。那些没有访问应用程序上下文的POJO怎么办?我必须首先在活动中获取上下文并将其传递给POJO吗?这似乎与使用Dagger进行DI的初衷背道而驰。 - Jordan
  1. 你说得对,我修复了 App 代码。如果你想要注入 App,你可以调用 inject()
  2. 每个包可以有不同的模块,但我认为按作用域(应用程序级别、活动级别等)划分不同的模块更有意义。
  3. 对于 POJOs,如果它们被一个 Component 注入过,你只需要在它们的构造函数上加上 @Inject 注解即可。这可能很难理解。如果你想在聊天室里讨论更多,我们可以再谈谈。
- Emmanuel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接