Не могу заставить dagger2 вводить модифицированные API в одноэлементный объект, а затем этот одноэлементный объект в фрагменты - PullRequest
0 голосов
/ 08 января 2019

Что мне нужно, это: Иметь одноэлементный объект DataStore DataStore выполнит http-запрос, поэтому в нем необходимо установить apis Retrofit, например (UserApi - это интерфейс для модификации)

Фрагменты и действия будут содержать 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)
        }
   }

DataStore

    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 в хранилище данных

Если я удаляю var mainApplication из хранилища данных, я получаю сообщение об ошибке, что TestApi не может быть предоставлен без конструктора @Inject .. в FormFragment

1 Ответ

0 голосов
/ 08 января 2019
    @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)
        }
   }

DataStore

    @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)
       }
...