无法使dagger2将改造api注入单例对象,然后将该单例对象注入片段

时间:2019-01-08 00:03:54

标签: android kotlin dagger-2

我需要的是: 具有单例对象DataStore DataStore会执行http请求,因此需要其中的Retrofit API,例如(UserApi-这是Retrofit接口)

片段和活动将包含DataStore,但它们也可以具有其他一些Api。

我需要的概念示例:

    class DataStore {
      @Inject lateinit var userApi: UserApi
    }

    class Fragment1 : Fragment() {
      @Inject lateinit var dataStore: DataStore
      @Inject lateinit var testApi: TestApi
    }

我设法将api注入通过工厂创建的ViewModel中,但是我需要单例数据存储,而且我知道应用程序依赖性是问题的一部分。将userApi注入FormFragment中似乎也存在问题。

这就是我所拥有的

MainApplication

class MainApplication : Application() {

lateinit var appComponent: AppComponent

override fun onCreate() {
    super.onCreate()
    StateSaver.setEnabledForAllActivitiesAndSupportFragments(this, true)

    appComponent = DaggerAppComponent.builder()
        .userModule(UserModule(this))
        .retrofitModule(RetrofitModule())
        .build()
    }

AppComponent

    @Singleton
    @Component(modules = [RetrofitModule::class, UserModule::class])
    interface AppComponent {

    fun inject(mainActivity: MainActivity)

    fun inject(formFragment: formFragment)

    fun inject(dataStore: DataStore)

    fun userApi(): UserApi

    fun testApi(): TestApi

}

UserModule

    @Module
    class UserModule(var mainApplication: MainApplication) {

      @Singleton
      @Provides
      fun provideDataStore() : DataStore = DataStore(mainApplication)
    }

RetrofitModule

    @Module
    class RetrofitModule {

        private val TAG: String = RetrofitModule::class.java.simpleName

        @Singleton
        @Provides
        fun provideRetrofit() : Retrofit {
            Log.e(TAG, "Creating retrofit ...")
            val httpClient = OkHttpClient.Builder()
                .addInterceptor {
                    val request = it.request()
                    if (BuildConfig.DEBUG) {
                        Log.d(TAG, "${request.method()}: ${request.url()}")
                    }

                    it.proceed(request)
               }
                .build()

            return Retrofit.Builder()
                .client(httpClient)
                .baseUrl("http://192.168.0.13:3000")
        .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
        .addConverterFactory(JacksonConverterFactory.create(jacksonObjectMapper()))
        .build()
        }

        @Provides
        fun provideUserApi(retrofit: Retrofit) : UserApi {
            return retrofit.create(UserApi::class.java)
        }

        @Provides
        fun provideTestApi(retrofit: Retrofit) : TestApi {
            return retrofit.create(TestApi::class.java)
        }
   }

数据存储

    class DataStore @Inject constructor(application: MainApplication) {

        init {
           application.appComponent.inject(this)
        }

        @Inject
        lateinit var userApi: userApi
        ...

FormFragment

    class FormFragment : Fragment() {

       @Inject
       lateinit var dataStore: DataStore

       @Inject
       lateinit var testApi: TestApi

       override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
           super.onViewCreated(view, savedInstanceState)
           val application = requireActivity().application as MainApplication

           application.appComponent.inject(this)
       }

我正在 MainApplication cannot be provided without an @Inject constructor or an @Provides-annotated method在DataStore

如果我从数据存储中删除var mainApplication,则会收到错误消息,即在FormFragment上没有@Inject构造函数时无法提供TestApi

1 个答案:

答案 0 :(得分:0)

    @Singleton class DataStore @Inject constructor(
        private val userApi: UserApi
    ) {
    }

    class Fragment1 : Fragment() {
      @Inject lateinit var dataStore: DataStore
      @Inject lateinit var testApi: TestApi
    }

class MainApplication : Application() {

    lateinit var appComponent: AppComponent

    override fun onCreate() {
        super.onCreate()
        StateSaver.setEnabledForAllActivitiesAndSupportFragments(this, true)

        appComponent = DaggerAppComponent.builder()
            .userModule(UserModule(this))
            .retrofitModule(RetrofitModule())
            .build()
        }

AppComponent

@Singleton
@Component(modules = [RetrofitModule::class, UserModule::class])
interface AppComponent {

    fun inject(mainActivity: MainActivity)

    fun inject(formFragment: formFragment)

    fun userApi(): UserApi

    fun testApi(): TestApi

}

UserModule

    @Module
    class UserModule(
        val mainApplication: MainApplication
    ) {
      @Provides
      fun app(): MainApplication = mainApplication

      // @Singleton
      // @Provides
      // fun provideDataStore() : DataStore = DataStore(mainApplication)
    }

RetrofitModule

    @Module
    class RetrofitModule {

        private val TAG: String = RetrofitModule::class.java.name

        @Singleton
        @Provides
        fun provideRetrofit() : Retrofit {
            Log.e(TAG, "Creating retrofit ...")
            val httpClient = OkHttpClient.Builder()
                .addInterceptor {
                    val request = it.request()
                    if (BuildConfig.DEBUG) {
                        Log.d(TAG, "${request.method()}: ${request.url()}")
                    }

                    it.proceed(request)
               }
                .build()

            return Retrofit.Builder()
                .client(httpClient)
                .baseUrl("http://192.168.0.13:3000/")
        .addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
        .addConverterFactory(JacksonConverterFactory.create(jacksonObjectMapper()))
        .build()
        }

        @Provides
        @Singleton
        fun provideUserApi(retrofit: Retrofit) : UserApi {
            return retrofit.create(UserApi::class.java)
        }

        @Provides
        @Singleton
        fun provideTestApi(retrofit: Retrofit) : TestApi {
            return retrofit.create(TestApi::class.java)
        }
   }

数据存储

    @Singleton class DataStore @Inject constructor(
        application: MainApplication
    ) {
        @Inject
        lateinit var userApi: userApi
        ...

FormFragment

    class FormFragment : Fragment() {

       @Inject
       lateinit var dataStore: DataStore

       @Inject
       lateinit var testApi: TestApi

       override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
           super.onViewCreated(view, savedInstanceState)
           val application = requireActivity().application as MainApplication

           application.appComponent.inject(this)
       }