从匕首 2 获取空实例

Posted

技术标签:

【中文标题】从匕首 2 获取空实例【英文标题】:Getting null instance from dagger 2 【发布时间】:2019-11-18 07:27:14 【问题描述】:

我正在开发一个应用程序,其中定义了多个层并使用 dagger2 进行实例管理等。我有管理器、服务和视图。

我正在尝试在 @Module 中设置管理器,例如:

@Module
class ManagerModule 

@Provides
@Singleton
fun provideDatabaseContext(userManager: UserManager) : DatabaseContext 
    var databaseContext : DatabaseContext = DatabaseContext();
    databaseContext.setUserManager(userManager)
    return databaseContext



@Provides
@Singleton
fun provideUserManager(store : PersistenceStore<DAOUser>) : UserManager = UserManager(store)

其中DatabaseContext是这样的:

class DatabaseContext : IDatabaseContext 


private lateinit var userManager: IUserManager


override fun getUserManager(): IUserManager 
    return userManager;


fun setUserManager(userManager: IUserManager)
    this.userManager = userManager;



当我像这样在我的服务中注入 DatabaseContext 时:

class UserService @Inject constructor(var databaseContext: IDatabaseContext) : IUserService 





override fun addUser(dtoUser: DTOUser, callback: ResponseCallback<Response<Void>>) 


    var daoUser : DAOUser = DAOUser(dtoUser.name, dtoUser.email, dtoUser.password)


    databaseContext.getUserManager().add(daoUser);
    callback.onCompletion(Response<Void>())


一切正常,除了 getUserManager() 一直为空,即使我有 setUserManager 方法并且我在 ManagerModule 中进行设置,如上所示。任何帮助,将不胜感激。谢谢

这里是服务模块

@Module
class ServicesModule 

@Provides
@Singleton
fun provideUserService() : UserService = UserService(DatabaseContext())

@Provides
@Singleton
fun provideAuthenticationService() : AuthenticationService = AuthenticationService(FirebaseAuth.getInstance())

【问题讨论】:

您将DatabaseContext 作为DatabaseContext 类型提供,而不是作为IDatabaseContext 提供,这是否是您的示例代码中的拼写错误?就像现在一样,@Provide 函数不能是用于注入 IDatabaseContext 的函数。如果您的代码像这样编译和运行,那么您在UserService 中获得的任何IDatabaseContext 都必须从其他地方提供。 目前是DatabaseContext。由于 IDatabaseContext 只是 DatabaseContext 继承的 getDatabaseContext 方法定义的接口 是的,我明白了。但是,如果您的方法返回DatabaseContext 类型,我相信您不应该将它作为IDatabaseContext 注入某处。您确定没有其他方法可以在某处提供具体的IDatabaseContext 类型吗? 是的,我已经在管理器模块中提供了具体的 DatabaseContext。就在 ServicesModule 中,我在构造函数中使用了 DatabaseContext。我在我的问题中添加了 ServicesModule 我认为在 ServicesModule 中我必须这样做 @Provides @ Singleton fun provideUserService(databaseContext : DatabaseContext()) : UserService = UserService(databaseContext ) 【参考方案1】:

我假设空值实际上是databaseContext 而不是getUserManager()。因为我不确定你如何实例化UserService

构造函数注入要求注入的类在提供参数类型的组件中实例化。在您的情况下,由于您没有它,那么您的 UserService 实际上并没有被注入。

此外,DatabaseContext 提供程序需要位于 userService() 所在的模块之一中,UserService 构造函数注入才能工作,您已经拥有了。

@Singleton
@Component(modules = [ManagerModule::class]) // ManagerModule has DatabaseContext provider
class MyComponent 
    fun userService(): UserService // this is how you get the instance of userService that is constructor injected. 

因为您的班级名称中包含 Service。我假设您想要它的单个实例。您可以使用 @Singleton 对其进行注释,这样每个 userService() 调用都会返回相同的对象,否则会创建一个新对象。

@Singleton
class UserService @Inject constructor(var databaseContext: IDatabaseContext) : IUserService

【讨论】:

I您的语法看起来像匕首 1,但在我的情况下,我使用的是匕首 2。还是在匕首 2 中会一样? dagger1语法是哪一种? 我刚刚修复了你的构造函数注入问题。我的意思是,还有另一种方法可以修复它,但必须删除构造函数注入。所以是的,即使在 dagger2 中,这也是进行构造函数注入的唯一方法。 是的,你的答案应该有效。但它现在不需要构造函数中的@Inject,因为您现在正在进行正常注入。 是的,不再需要构造函数注入,因为您明确使用了UserService(databaseContext)【参考方案2】:

我在 ServicesModule 的方法中传递错误。所以我不得不像这样在方法中传递它并且它起作用了:

 @Provides 
 @Singleton 
 fun provideUserService(databaseContext : DatabaseContext()) : UserService = UserService(databaseContext )

【讨论】:

以上是关于从匕首 2 获取空实例的主要内容,如果未能解决你的问题,请参考以下文章

匕首可以使android活动创建速度变慢吗?

获取 GCM 实例 ID 的空指针

从 NIB 加载后 IBOutlet 实例为(空)

尝试从 PHAsset 获取 AVAssetExportSession 的输出时得到空结果

支持向量机实例讲解

EC2:从实例本身中获取实例 ID [重复]