- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我从头开始开发一个新的 Android 项目。在了解项目范围和请求的功能后,我提出了一个模块化架构(基本上将每个功能包装到一个功能或 android 模块中),如下所示
一切看起来都很完美,直到我想引入 dagger 来粘合所有模块。问题是我希望每个模块都有自己的 dagger 组件/子组件及其模块,以便提供依赖项并向它们公开要由其他组件或父组件使用的图形。
Google 官方 dagger 文档指出子组件可以直接访问父组件依赖项,反之则不然。然而,在我的例子中,基本组件需要来自数据模块的依赖关系,而后者本身需要来自网络模块的依赖关系。
知道我希望每个 Android 模块最好都有自己的子组件,这个问题有什么解决方案吗?如果不行的话有什么解决办法吗?
谢谢。
编辑:这是我的项目结构的样子
这就是我设置 Dagger 图的方式
我的AppComponent(Dagger根)
@Singleton
@Component(modules = {
AppModule.class,
ActivityBuilder.class,
AndroidSupportInjectionModule.class
})
public interface AppComponent {
void inject(CatApp application);
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
AppComponent build();
}
}
我的应用程序模块
@Module(subcomponents = DataComponent.class)
public class AppModule {
@Provides
@Singleton
Context provideContext(Application application) {
return application.getApplicationContext();
}
}
我的DataComponent(位于数据android模块)
@Subcomponent(modules = DataModule.class)
public interface DataComponent {
@Subcomponent.Builder
interface Builder {
DataComponent build();
}
}
数据模块(位于data android模块)应该提供SystemManager
的实现
@Module(subcomponents = NetworkComponent.class)
public class DataModule {
@Provides
@Singleton
ISystemManager provideSystemManager(SystemManager systemManager) {
return systemManager;
}
}
网络组件(位于网络Android模块)
@Subcomponent(modules = NetworkModule.class)
public interface NetworkComponent {
@Subcomponent.Builder
interface Builder {
NetworkComponent build();
}
}
网络模块(位于网络 Android 模块)并应提供 INetWorkManager
的实现
@Module
public class NetworkModule {
@Provides
@Singleton
INetworkManager provideNetworkManager(NetworkManager networkManager) {
return networkManager;
}
}
我在所有构造函数中使用 @Inject
注释,因此我的配置已全部设置完毕,但问题是 dagger 由于某种原因不会编译这些子组件,并且在编译时出现此错误:
Error:(27, 8) error: [dagger.android.AndroidInjector.inject(T)] com.github.andromedcodes.network.INetworkManager cannot be provided without an @Provides-annotated method.
com.github.andromedcodes.network.INetworkManager is injected at
com.github.andromedcodes.data.SystemManager.<init>(networkManager)
com.github.andromedcodes.data.SystemManager is injected at
com.github.andromedcodes.data.di.DataModule.provideSystemManager(systemManager)
com.github.andromedcodes.domain.managers.ISystemManager is injected at
com.github.andromedcodes.domain.interactors.CheckSystemAvailability.<init>(systemManager)
com.github.andromedcodes.domain.interactors.CheckSystemAvailability is injected at
com.github.andromedcodes.chasseautrsor.views.Splash.SplashPresenter.<init>(checkSystemAvailability)
com.github.andromedcodes.chasseautrsor.views.Splash.SplashPresenter is injected at
com.github.andromedcodes.chasseautrsor.di.SplashModule.bindSplashPresenter(presenter)
com.github.andromedcodes.chasseautrsor.views.Contract.Presenter is injected at
com.github.andromedcodes.mvp.BaseActivity.mPresenter
com.github.andromedcodes.chasseautrsor.views.SplashScreenActivity is injected at
dagger.android.AndroidInjector.inject(arg0)
知道我想在数据 android 模块提供 ISystemManager 实现并在网络 Android 模块提供 INetworkManager ,如何解决此问题?
谢谢。
最佳答案
子组件自动可以访问父组件图中绑定(bind)的对象,这是有道理的,因为子组件只有一个父组件 - 没有歧义。父组件无法自动访问子组件的图表,因为您可以根据需要创建任意数量的子组件实例;目前尚不清楚您要尝试访问哪个实例。一般来说,除非您需要对象图的不同变体(您可以在 Guice 中使用私有(private)模块或子注入(inject)器来实现),或者除非您想隐藏实现细节(例如内部网络对象),否则您最好将所有模块安装在同一个组件中并跳过子组件策略。
但是,如果您确实想要分离图表或创建多个子组件实例,您也可以在作用域 @Provides
方法中创建子组件实例。这样,NetworkComponent 就有一个带有私有(private)绑定(bind)的单独图,但也可以使用您在 AppComponent 中公开的依赖项,并且您还可以确保图中只有一个 NetworkComponent 及其相关绑定(bind)的副本。您还需要在子组件上放置一个 getter(提供方法或工厂方法),以便您可以从外部访问它的一些绑定(bind),这与您需要在 @Component 上使用 getter 或注入(inject)器方法才能发挥作用完全相同。
@Subcomponent(modules = NetworkModule.class)
public interface NetworkComponent {
/** Allow anyone with a NetworkComponent instance to get the INetworkManager. */
INetworkManager getINetworkManager();
@Subcomponent.Builder
interface Builder {
NetworkComponent build();
}
}
/**
* Creates a singleton NetworkComponent. Install this in AppComponent's module,
* or in your data module if that encapsulates network calls.
*/
@Singleton @Provides NetworkComponent networkComponent(
NetworkComponent.Builder builder) {
return builder.build();
}
/** Make the INetworkManager accessible, but not the NetworkManager impl. */
@Provides static provideNetworkManager(NetworkComponent networkComponent) {
return networkComponent.getINetworkManager(); // add this to NetworkComponent
}
<小时/>
如需进一步引用,请参阅the "Subcomponents for Encapsulation" section有关子组件的 Dagger 2 文档中的内容:
Another reason to use subcomponents is to encapsulate different parts of your application from each other. For example, if two services in your server (or two screens in your application) share some bindings, say those used for authentication and authorization, but each have other bindings that really have nothing to do with each other, it might make sense to create separate subcomponents for each service or screen, and to put the shared bindings into the parent component.
In the following example, the Database is provided within the
@Singleton
component, but all of its implementation details are encapsulated within the DatabaseComponent. Rest assured that no UI will have access to the DatabaseConnectionPool to schedule their own queries without going through the Database since that binding only exists in the subcomponent.
关于java - 在 Android 模块化项目中使用 Dagger 2.11,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49260158/
每个人(希望)都在努力实现代码模块化。我想要做的是有 1 个主要的 Sass 文件,它导入我的所有模块,这些模块是局部的,如果需要,这些局部可以调用它们自己的局部组。我想要的是,不是在我的代码库中调用
如何在 xslt 转换中模块化一组重复的输出?例如,我有如下内容(伪代码)。 并
假设我有几个简单的模型驻留在 food.py 中: import peewee as pw db = pw.SqliteDatabase('food.db') class BaseModel(pw.M
我正在开始一个新的 Angular 项目并尝试模块化我的所有代码——我厌倦了拥有大量的 app.js 文件,而且因为我正在为一家公司开发一个平台,所以我的代码整洁且模块化以便于测试、清洁和易于过渡到
所以,有人告诉我,在 nodeJS 中传递 request 和或 response 变量是“不好的做法”。但这意味着你的大部分代码都必须在 server.js 文件中,这使得它变得困惑而且有点难看。
有一个想法:函数(在 FP 中)可以以与 OOP 中的组件类似的方式组成。对于 OOP 中的组件,我们使用接口(interface)。对于函数,我们可以使用委托(delegate)。目标是实现分解、模
有没有办法将 SQL 代码模块化,使其更具可读性和可测试性? 我的 SQL 代码经常变成一长串复杂的嵌套连接、内连接等,难以编写和调试。相比之下,在像 Javascript 或 Java 这样的过程语
我想知道大公司如何倾向于在他们的页面上模块化组件。 Facebook 就是一个很好的例子: There's a team working on Search that has its own CSS,
我正在寻找在 WPF 中构建模块化应用程序模型的解决方案。目前,我使用 Devexpress POCO MVVM 来构建我的 WPF 应用程序,但缺乏模块化的可扩展性,我正在寻找适合我当前设计并允许构
我制作了一个 Gradle 项目,它使用类加载器从子目录资源/文本中加载文本文件。此时它可以工作,但是当我将项目转换为模块化 JavaFX 程序时,相同的类加载器函数会给出 NullPointerEx
假设我有一个通用类模块: export class MyCalc { data = {} ... } 并说我想扩展更多功能: export class MyCalcLoader {
我的模板文件变得越来越大并且过于复杂(大约 200 行(长)代码,9 级缩进),因此它也变得容易出错。我正在寻找一个简单的解决方案,它可以让我轻松访问 $scope 变量和函数。 我的第一个想法是使用
许多人说要将外部 CSS 和 JavaScript 文件的数量保持在最低限度以减少往返时间。例如,Google 建议每个网站最多分别使用两个 CSS 和 JavaScript 文件。 问题是,作为“模
我试图找出为什么我的 Promise 链执行无序,尽管编写了一个非嵌套的 then 链。我的函数已经模块化,以减少链中发生的代码膨胀(我期望有五个 then 方法),并且我不确定这些模块中的某些内容是
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 8 年前。 Improv
我使用 create-react-app 创建了一个样板 React 应用程序。 现在,在我的 App.js 文件中 import classes from './App.css'; 我做到了
Java 模块系统是否应该阻止模块通过反射访问其他模块,而不声明正确的模块依赖关系? 例如,在编译这个 hello world Java 11 类时,它从另一个模块调用类,正如预期的那样,它不会编译,
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我的应用程序上有许多不同的“控制元素”:下拉菜单、选项卡、菜单等。在同一页面上,有许多相同的控件。当编写 JavaScript 来处理与每个控件关联的不同事件时,我试图使我的代码尽可能干燥。挑战之一是
处理以下场景的模块化方式是什么:应用程序具有所有标题标签(h1、h2、h3 等)的通用样式。特定组件 Widget.jsx 可以使用这些标题中的任何一个,但 h1 标签具有特殊样式。在 CSS 的“旧
我是一名优秀的程序员,十分优秀!