android - 如果没有@Provides注释的方法,则无法提供Dagger/MissingBinding androidx.lifecycle.ViewModelProvider.Factory

标签 android kotlin viewmodel dagger-2

我正在尝试在我的项目中实现ViewModel Factory,但是在使用Dagger 2实现它时遇到了一些问题。我提供了必要的代码,您可以看一下让我知道如何提出建议。

我有所有需要提供的方法。我还要提及的是,我试图通过ViewModelFactory将参数(存储库)传递给ViewModel类,这是我得到错误的地方。

这是我正在使用的所有班级:

HomeViewModel.kt

class HomeViewModel @Inject constructor(
        private val  categoriesRepository: CategoriesRepository) : ViewModel() {

    val categories by lazyDefferd {
        categoriesRepository.getCategories()
        Log.d("All_Categories", "")
    }
}


HomeViewModelFactory.kt

@Suppress("UNCHECKED_CAST")
@Singleton
class HomeViewModelFactory @Inject constructor
    (private val viewModelsMAp: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>)
        : ViewModelProvider.Factory {

    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        val creator = viewModelsMAp[modelClass] ?: viewModelsMAp.entries.firstOrNull {
            modelClass.isAssignableFrom(it.key)
        }?.value ?: throw ViewModelNotFound()
        try {
            return creator.get() as T
        } catch (e: Exception) {
            throw RuntimeException(e)
        }
    }
}


HomeFragment.kt

class HomeFragment : Fragment() {

    @Inject
    lateinit var factory: ViewModelProvider.Factory

    private lateinit var viewModel: HomeViewModel

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


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        val view = inflater.inflate(R.layout.home_fragment, container, false)

        return view
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Injector.appComponent.inject(this)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        viewModel = ViewModelProviders.of(this, factory).get(HomeViewModel::class.java)

        GlobalScope.launch {
            val categories = viewModel.categories.await()
            Log.d("Responses", "$categories")
        }

    }



匕首:
AppComponent.kt

@Singleton
@Component(
        modules = [AppModule::class, NetworkModule::class]
)
interface AppComponent {
    fun inject(homeFragment: HomeFragment)
}


AppModule.kt

@Module
class AppModule(
        val application : Context) {

    @Provides
    fun providesApplication(): Context = application

    @Provides
    @Singleton
    fun provideDb(app: Application): AppDatabase {
        return Room.databaseBuilder(app, AppDatabase::class.java, "my.db")
                .build()
    }

    @Provides
    @Singleton
    fun providesCategoryDao(db: AppDatabase) : CategoryDao {
        return db.categoryDao()
    }

    @Provides
    @Singleton
    fun providesSubCategoryDao(db: AppDatabase): SubCategoryDao {
        return db.subcategoryDao()
    }

    @Provides
    fun provideCategoryRepository(db: AppDatabase, apiService: ApiService) : CategoriesRepository {
        return CategoriesRepository(db.categoryDao(), apiService)
    }
}


NetworkMOdule.kt

@Module
class NetworkModule {


    /**
     * Provide the Api Service implementation
     * @param retrofit the Retrofit object used to instantiate the service
     * @return the api service implementation
     */
    @Provides
    @Singleton
    fun providesApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }


    /**
     * Provides Retrofit object
     * @return the Retrofit object
     */
    @Provides
    @Singleton
    fun providesRetrofit(): Retrofit {
        return Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addCallAdapterFactory(CoroutineCallAdapterFactory())
                .addConverterFactory(GsonConverterFactory.create())
                .build()
    }
}


ViewModelKey.kt

@MustBeDocumented
@Target(
        AnnotationTarget.FUNCTION,
        AnnotationTarget.PROPERTY_GETTER,
        AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)


ViewModelModule.kt

@Suppress("unused")
@Module
abstract class ViewModelModule {

    @Binds
    @IntoMap
    @ViewModelKey(HomeViewModel::class)
    abstract fun bindHomeViewModel(homeViewModel: HomeViewModel): ViewModel

    @Binds
    abstract fun bindHomeViewModelFactory(homeViewModelFactory: HomeViewModelFactory): ViewModelProvider.Factory
}


喷射器

class Injector {

    companion object {

        lateinit var appComponent: AppComponent

        fun  initAppComponent(appModule: AppModule, networkModule: NetworkModule) {
            appComponent = DaggerAppComponent.builder()
                    .appModule(appModule)
                    .networkModule(networkModule)
                    .build()
        }
    }
}


编译后,我得到:

C:\Users\vvasilev\Documents\Projects\myproject-android\app\build\tmp\kapt3\stubs\debug\com\myproject\vascovasilev\myproject\dagger\components\AppComponent.java:10: error: [Dagger/MissingBinding] androidx.lifecycle.ViewModelProvider.Factory cannot be provided without an @Provides-annotated method.
    public abstract void inject(@org.jetbrains.annotations.NotNull()
                         ^
      androidx.lifecycle.ViewModelProvider.Factory is injected at
          com.myproject.vascovasilev.myproject.ui.fragments.home.HomeFragment.factory
      com.myproject.vascovasilev.myproject.ui.fragments.home.HomeFragment is injected at
          com.myproject.vascovasilev.myproject.dagger.components.AppComponent.inject(com.myproject.vascovasilev.myproject.ui.fragments.home.HomeFragment)

最佳答案

我认为在AppComponent中您忘记添加ViewModelModule


  @Singleton
  @Component(modules = [
    AndroidSupportInjectionModule::class,
    AppModule::class,
    NetworkModule::class
    ViewModelModule::class
])
interface AppComponent : AndroidInjector<DaggerApplication> {

    /**
     * component builder
     */
    @Component.Builder
    interface Builder {
        /**
         * get builder
         * @param application
         */
        @BindsInstance
        fun application(application: Application): Builder

        /**
         * build appcomponent
         */
        fun build(): AppComponent
    }
}

关于android - 如果没有@Provides注释的方法,则无法提供Dagger/MissingBinding androidx.lifecycle.ViewModelProvider.Factory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55358762/

相关文章:

Android Studio 上的 Android 虚拟设备错误

asp.net-mvc - Viewmodel 和动态菜单最佳实践 - ASP.NET MVC

java - getPreferenceScreen().findPreference 与 findPreference 之间的区别

android - Socialauth-android 获取oAuth-token并使用设备上的账户信息

kotlin - 如何启动并行协程并返回结果

android - 引用生成类的适配器 (android-sunflower)

user-interface - 如何删除在borderpane上添加的Fragment()?

c# - 在同一个 Controller ActionResult 中运行我的存储库中的 2 个方法是否正确?

java - AfterCompose 与 Init ZK

android - 如何在 ExpandableListView 中获取粘性/固定标题?