java.lang.RuntimeException: 无法创建 class com.example.cookpadapp.viewmodel.CookpadViewModel+ 的实例
java.lang.RuntimeException: Cannot create an instance of class com.example.cookpadapp.viewmodel.CookpadViewModel+ at
我正在开发食谱 android 应用程序并使用 koin 依赖注入但是当我 运行 项目时我得到以下异常 ]
java.lang.RuntimeException: Cannot create an instance of class com.example.cookpadapp.viewmodel.CookpadViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:188)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:238)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:113)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:169)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:44)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:31)
at com.example.cookpadapp.CookpadFragment.getViewModel(CookpadFragment.kt:21)
at com.example.cookpadapp.CookpadFragment.initObservers(CookpadFragment.kt:41)
at com.example.cookpadapp.CookpadFragment.onViewCreated(CookpadFragment.kt:30)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1392)
at android.app.Activity.performStart(Activity.java:7252)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3000)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:185)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:170)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:147)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:73)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1858)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6820)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:922)
Caused by: java.lang.InstantiationException: java.lang.Class<com.example.cookpadapp.viewmodel.CookpadViewModel> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
低于我的 CookpadViewModel.kt
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.cookpadapp.domain.use_case.GetRecipeUseCase
import com.example.cookpadapp.domain.utils.fold
import com.example.cookpadapp.model.Recipe
import com.example.cookpadapp.model.RecipeResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class CookpadViewModel(private val recipeUseCase: GetRecipeUseCase) : ViewModel() {
var cookpad = MutableLiveData<RecipeResponse>()
// Expose to the outside world
val error = MutableLiveData<String>()
var progress = MutableLiveData(false)
init {
getRecipes()
}
fun getRecipes() {
progress.postValue(true)
viewModelScope.launch(Dispatchers.IO) {
recipeUseCase.invoke()
.fold({ recipeResponse->
cookpad.postValue(recipeResponse)
}, {
error.postValue(it.message)
})
progress.postValue(false)
}
}
fun onRecipeClicked(recipe: Recipe) {
}
}
低于我的CookpadFragment.kt
package com.example.cookpadapp
import android.os.BaseBundle
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.example.cookpadapp.databinding.FragmentCookpadBinding
import com.example.cookpadapp.ui.BaseFragment
import com.example.cookpadapp.ui.adapter.RecipeAdapter
import com.example.cookpadapp.viewmodel.CookpadViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
// TODO: item_recipe, RecipeAdapter, fragment_cookpad
class CookpadFragment : BaseFragment<FragmentCookpadBinding>() {
override val layoutId: Int = R.layout.fragment_cookpad
private val viewModel: CookpadViewModel by viewModels()
private val adapter = RecipeAdapter(arrayListOf()) { recipe ->
viewModel.onRecipeClicked(recipe)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
initObservers()
}
private fun initViews() {
binding.recipeRV.adapter = adapter
binding.swipeRefresh.setOnRefreshListener {
viewModel.getRecipes()
}
}
private fun initObservers() {
viewModel.cookpad.observe(viewLifecycleOwner) { recipes ->
adapter.update(recipes)
}
viewModel.progress.observe(viewLifecycleOwner) { loading ->
binding.swipeRefresh.isRefreshing = loading
}
}
}
在我的 Modules.kt 下面我已经实现了 koin 逻辑
object Modules {
val viewModels = module {
viewModel { CookpadViewModel(get()) }
viewModel{DetailCookpadViewModel(get())}
}
val apiModule = module {
factory { CookpadRepository(get()) }
factory { GetRecipeUseCase(get()) }
factory { GetRecipeDetailsUseCase(get()) }
single<CookpadInterface> {
provideRetrofit(get<OkHttpClient>())
}
factory<OkHttpClient> {
provideOkHttpClient(get<Cache>())
}
factory<Cache> {
provideCache(get<Context>())
}
}
}
fun provideCache(context: Context): Cache {
val cacheSize: Long = 10 * 1024 * 1024
return Cache(context.cacheDir, cacheSize)
}
fun provideOkHttpClient(cache: Cache): OkHttpClient {
val logger = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
return OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.cache(cache)
.addInterceptor(logger)
.build()
}
fun provideRetrofit(okHttpClient: OkHttpClient): CookpadInterface {
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())
.build()
.create(CookpadInterface::class.java)
}
低于GetRecipeUseCase.kt
class GetRecipeUseCase(
private val cookpadRepository: CookpadRepository
) {
suspend operator fun invoke() = cookpadRepository.getRecipes()
}
我想知道我究竟在哪里犯了错误我已经按照所有 Whosebug 的回答它没有解决我的问题
我通过在 CookpadFragment 中导入和添加以下方式解决了我的问题
private val viewModel: CookpadViewModel by viewModel()
import org.koin.androidx.viewmodel.ext.android.viewModel
我正在开发食谱 android 应用程序并使用 koin 依赖注入但是当我 运行 项目时我得到以下异常 ]
java.lang.RuntimeException: Cannot create an instance of class com.example.cookpadapp.viewmodel.CookpadViewModel
at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:188)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:238)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:113)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:169)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:44)
at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:31)
at com.example.cookpadapp.CookpadFragment.getViewModel(CookpadFragment.kt:21)
at com.example.cookpadapp.CookpadFragment.initObservers(CookpadFragment.kt:41)
at com.example.cookpadapp.CookpadFragment.onViewCreated(CookpadFragment.kt:30)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2987)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:3065)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:2988)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:546)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:112)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1647)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3128)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1392)
at android.app.Activity.performStart(Activity.java:7252)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3000)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:185)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:170)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:147)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:73)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1858)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:201)
at android.app.ActivityThread.main(ActivityThread.java:6820)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:547)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:922)
Caused by: java.lang.InstantiationException: java.lang.Class<com.example.cookpadapp.viewmodel.CookpadViewModel> has no zero argument constructor
at java.lang.Class.newInstance(Native Method)
低于我的 CookpadViewModel.kt
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.cookpadapp.domain.use_case.GetRecipeUseCase
import com.example.cookpadapp.domain.utils.fold
import com.example.cookpadapp.model.Recipe
import com.example.cookpadapp.model.RecipeResponse
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class CookpadViewModel(private val recipeUseCase: GetRecipeUseCase) : ViewModel() {
var cookpad = MutableLiveData<RecipeResponse>()
// Expose to the outside world
val error = MutableLiveData<String>()
var progress = MutableLiveData(false)
init {
getRecipes()
}
fun getRecipes() {
progress.postValue(true)
viewModelScope.launch(Dispatchers.IO) {
recipeUseCase.invoke()
.fold({ recipeResponse->
cookpad.postValue(recipeResponse)
}, {
error.postValue(it.message)
})
progress.postValue(false)
}
}
fun onRecipeClicked(recipe: Recipe) {
} }
低于我的CookpadFragment.kt
package com.example.cookpadapp
import android.os.BaseBundle
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.example.cookpadapp.databinding.FragmentCookpadBinding
import com.example.cookpadapp.ui.BaseFragment
import com.example.cookpadapp.ui.adapter.RecipeAdapter
import com.example.cookpadapp.viewmodel.CookpadViewModel
import org.koin.androidx.viewmodel.ext.android.viewModel
// TODO: item_recipe, RecipeAdapter, fragment_cookpad
class CookpadFragment : BaseFragment<FragmentCookpadBinding>() {
override val layoutId: Int = R.layout.fragment_cookpad
private val viewModel: CookpadViewModel by viewModels()
private val adapter = RecipeAdapter(arrayListOf()) { recipe ->
viewModel.onRecipeClicked(recipe)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViews()
initObservers()
}
private fun initViews() {
binding.recipeRV.adapter = adapter
binding.swipeRefresh.setOnRefreshListener {
viewModel.getRecipes()
}
}
private fun initObservers() {
viewModel.cookpad.observe(viewLifecycleOwner) { recipes ->
adapter.update(recipes)
}
viewModel.progress.observe(viewLifecycleOwner) { loading ->
binding.swipeRefresh.isRefreshing = loading
}
}
}
在我的 Modules.kt 下面我已经实现了 koin 逻辑
object Modules {
val viewModels = module {
viewModel { CookpadViewModel(get()) }
viewModel{DetailCookpadViewModel(get())}
}
val apiModule = module {
factory { CookpadRepository(get()) }
factory { GetRecipeUseCase(get()) }
factory { GetRecipeDetailsUseCase(get()) }
single<CookpadInterface> {
provideRetrofit(get<OkHttpClient>())
}
factory<OkHttpClient> {
provideOkHttpClient(get<Cache>())
}
factory<Cache> {
provideCache(get<Context>())
}
}
}
fun provideCache(context: Context): Cache {
val cacheSize: Long = 10 * 1024 * 1024
return Cache(context.cacheDir, cacheSize)
}
fun provideOkHttpClient(cache: Cache): OkHttpClient {
val logger = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
return OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.cache(cache)
.addInterceptor(logger)
.build()
}
fun provideRetrofit(okHttpClient: OkHttpClient): CookpadInterface {
return Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())
.build()
.create(CookpadInterface::class.java)
}
低于GetRecipeUseCase.kt
class GetRecipeUseCase(
private val cookpadRepository: CookpadRepository
) {
suspend operator fun invoke() = cookpadRepository.getRecipes()
}
我想知道我究竟在哪里犯了错误我已经按照所有 Whosebug 的回答它没有解决我的问题
我通过在 CookpadFragment 中导入和添加以下方式解决了我的问题
private val viewModel: CookpadViewModel by viewModel()
import org.koin.androidx.viewmodel.ext.android.viewModel