我正在尝试在我的项目中实现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
}
Injector.kt
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)
答案 0 :(得分:0)
在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
}
}