【问题标题】:Inject doesn't work with second constructor注入不适用于第二个构造函数
【发布时间】:2018-01-17 20:30:01
【问题描述】:

对于我当前的项目,我使用的是 Kotlin 和 Dagger 2。 我想在辅助构造函数中注入依赖项,但构造函数永远不会被初始化。

class SelectionFragmentModel ():ViewModel(){
   lateinit var channelInfosRepository: ChannelInfosRepository
   @Inject constructor(channelInfosRepository: ChannelInfosRepository) : this(){
      this.channelInfosRepository = channelInfosRepository
   }
   ...
}

作为一种解决方法,我目前正在注入主构造函数,但这不是最佳的。

class SelectionFragmentModel @Inject constructor(private val channelInfosRepository: ChannelInfosRepository):ViewModel(){
   constructor() : this(ChannelInfosRepository())
   ...
}

我错过了什么吗?

【问题讨论】:

  • 你的意思是没有参数的构造函数?
  • 主构造函数应该没有参数,注入应该发生在辅助构造函数中
  • Kotlin 中并非如此。从文档A class in Kotlin can have a primary constructor and one or more secondary constructors. The primary constructor is part of the class header: it goes after the class name (and optional type parameters) 中检查这一点
  • @user3517658 有什么解决办法吗?
  • 任何解决方案?

标签: kotlin dagger-2 dagger


【解决方案1】:

确保您的 SelectionFragmentModel只有一个构造函数。就 Kotlin 语言习语而言,构造函数是主要的还是次要的并不重要。在SelectionFragmentModel 中将只使用一个构造函数。

以下代码没有为初始化程序留下关于使用哪个构造函数的选项,因为只有一个!

class SelectionFragmentModel: ViewModel {
    lateinit var channelInfosRepository: ChannelInfosRepository

    @Inject constructor(channelInfosRepository: ChannelInfosRepository) : super() {
        this.channelInfosRepository = channelInfosRepository
    }
}

示例(有效)

在本例中,我们使用 dagger 进行默认设置:

  1. @Module注解类,为我们提供ChannelInfosRepository
  2. 修改SelectionFragmentModel(代码位于示例上方);
  3. @Component 注释的接口带有仅由一个模块组成的模块列表;
  4. 其他一切都只是 Android 的东西。

这是模块:

@Module
class AppModule {
    @Provides
    @Singleton
    fun providesChannelInfosRepository(): ChannelInfosRepository {
        return ChannelInfosRepository()
    }
}

@Component注解的接口:

@Singleton
@Component(modules = [AppModule::class])
interface AppComponent {
    fun inject(fragment: MainFragment)
}

这是AppComponent 的实例化方式。 MyApplication 必须在AndroidManifest.xml 中提及。

class MyApplication : Application() {
    var appComponent: AppComponent? = null
        private set

    override fun onCreate() {
        super.onCreate()

        appComponent = DaggerAppComponent.builder()
                .appModule(AppModule())
                .build()
    }
}

使用AppComponent 注入SelectionFragmentModel 的片段:

class MainFragment : Fragment() {

    @Inject
    lateinit var selectionFragmentModel: SelectionFragmentModel

    companion object {
        fun newInstance() = MainFragment()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // Ugly but fine for a test
        (activity?.application as? MyApplication)?.appComponent?.inject(this)
    }

    // onCreateView and other stuff ...

    @SuppressLint("SetTextI18n")
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        println("ViewModel address = ${selectionFragmentModel}")
        println("ChannelInfosRepository address = ${selectionFragmentModel.channelInfosRepository}")
    }
}

结果(而不是打印结果,我将其显示在 TextView 中):

【讨论】:

    猜你喜欢
    • 2012-05-08
    • 2015-05-14
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多