Hilt不支持非epmty构造函数模块。如果需要从匕首部分迁移到Hilt,那么如何将具有非空构造器的遗留匕首模块的依赖注入到hilt组件(如HiltViewModel )。
// Legacy Dagger module
@Module
public class DaggerModule {
private final Boolean customBoolean;
DaggerModule(Boolean customBoolean) {
this.customBoolean = customBoolean;
}
@Provides
@Singleton
CustomClass provideCustomClass() {
return CustomClass(customBoolean);
}
}
@Module
public class AnotherDaggerModule {
@Provides
@Singleton
AnotherClassDepndsOnCustomClass provideAnotherClass(CustomClass customClass) {
return AnotherClassDepndsOnCustomClass(customClass);
}
}// Migrated Hilt module
@HiltViewModel
class HiltViewModel @Inject constructor(
private val anotherClass: AnotherClassDepndsOnCustomClass
) : ViewModel() {
...
}既然我们在初始化模块时没有使用组件传递一些自定义参数,那么有没有我不知道已经存在的解决方案?
在运行应用程序时,应用程序由于错误DaggerModule must be set而崩溃。
发布于 2022-11-11 22:44:53
你需要重构。
关于迁移到希尔特的文档在标题“处理组件参数”下描述了这种情况,因为否则可实例化模块将被视为通过Builder或Factory传递的组件参数。
Hilt组件不能使用组件参数,因为组件的初始化对用户是隐藏的。..。 如果您的组件有任何其他参数--或者通过传递给构建器的模块实例,或者@BindsInstance,那么在处理这些参数时阅读这个部分。一旦您处理了这些,您就可以删除您的
@Component.Builder接口,因为它将被使用。
在“组件参数”下,Hilt文档确认需要重构:
由于组件实例化在使用Hilt时是隐藏的,所以不可能使用模块实例或
@BindsInstance调用在您自己的组件参数中添加。如果组件中包含这些内容,则需要重构代码以避免使用这些代码。
您可以考虑其中的一些结构:
替换模块/子类模块
在您的示例中,您可能需要创建一个为CustomClass提供绑定的替换模块。这可能就像子类模块和提供一个公共的无arg构造函数一样简单,该构造函数提供super(value)构造函数调用模块所需的功能。如果模块在图中只获得一个值(但可能在单独的应用程序中得到一个不同的值),那么这可能就足够了。
@Module
public class AdaptedDaggerModule extends DaggerModule {
AdaptedDaggerModule() {
super(true);
}
}注意,模块子类在实用程序和不应用于测试重写。方面有一定的限制。
自定义子组件
但是,您还在注释中编写了“组件是在需要使用的相应模块中创建的”,您可以使用Hilt中的自定义子组件继续这样做,并在javadoc或主Dagger子组件文档中提供更全面的文档。因为您将通过对Builder或Factory的显式调用来创建此组件,所以您可以在那里提供模块实例。子组件从其父组件继承绑定,因此可以避免指定整个模块列表。
请注意,如果您有一个密集的树,并具有对构造函数中提供的实例的多个引用,那么作为子组件这样做是非常有价值的。如果这只是将基于图的构造函数参数与一次性构造函数参数组合在一起的问题,那么辅助注射可能是一个更好的选择。
/** Subcomponents are usually declared on modules. You can also reuse one you have. */
@Module(subcomponents={YourSubcomponent.class})
public interface IncludeThisInYourHiltModuleList {}
@Subcomponent(modules={DaggerModule.class, AnotherDaggerModule.class})
public interface YourSubcomponent {
AnotherClassDepndsOnCustomClass anotherClass();
@Subcomponent.Builder
interface Builder {
Builder daggerModule(DaggerModule daggerModule); // arbitrary name
YourSubcomponent build(); // arbitrary name
}
}@HiltViewModel
class HiltViewModel @Inject constructor(
private val yourSubcomponentBuilder: YourSubcomponent.Builder
) : ViewModel() {
fun yourMethod() {
val subcomponent =
yourSubcomponentBuilder.daggerModule(DaggerModule(false)).build()
val anotherClass = subcomponent.anotherClass()
// ...
}
}Hilt托管组件中的构造函数值
最困难的情况是模块需要在每个Hilt管理组件中单独的值,例如每个需要传递不同构造函数参数的活动。在这种情况下,您可能需要将customBoolean (或其他参数)重新定义为从活动实例本身派生值。这保持了Hilt的期望,即它可以为Android不可预测地创建或重新创建的每个活动实例创建一个活动组件,并且它可以这样做,而无需指定任何其他构造函数参数。
https://stackoverflow.com/questions/74297249
复制相似问题