Got a error when I try to launch the app with the emulator. Try to look up the AlbumListFragment errors at line: 40 and 41. I can't understand what I have done wrong. Have implemented this code severals times without errors.
I also use android:text="@{viewModel.response}" inside the fragment layout. I don't think databinding is the problem.
Anyone see what I do wrong?
2022-04-03 18:25:22.687 4959-4959/com.example.mvvmretrofit E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.mvvmretrofit, PID: 4959
java.lang.RuntimeException: Cannot create an instance of class com.example.retrotest.ui.AlbumsViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:230)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:169)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)
at com.example.retrotest.ui.AlbumListFragment$onCreateView$viewModel$2.invoke(AlbumListFragment.kt:41)
at com.example.retrotest.ui.AlbumListFragment$onCreateView$viewModel$2.invoke(AlbumListFragment.kt:40)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.example.retrotest.ui.AlbumListFragment.onCreateView$lambda-0(AlbumListFragment.kt:40)
at com.example.retrotest.ui.AlbumListFragment.onCreateView(AlbumListFragment.kt:43)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1435)
at android.app.Activity.performStart(Activity.java:8018)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3475)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Caused by: java.lang.NoSuchMethodException: com.example.retrotest.ui.AlbumsViewModel.<init> [class android.app.Application]
at java.lang.Class.getConstructor0(Class.java:2332)
at java.lang.Class.getConstructor(Class.java:1728)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:228)
at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:169)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)
at com.example.retrotest.ui.AlbumListFragment$onCreateView$viewModel$2.invoke(AlbumListFragment.kt:41)
at com.example.retrotest.ui.AlbumListFragment$onCreateView$viewModel$2.invoke(AlbumListFragment.kt:40)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.example.retrotest.ui.AlbumListFragment.onCreateView$lambda-0(AlbumListFragment.kt:40)
at com.example.retrotest.ui.AlbumListFragment.onCreateView(AlbumListFragment.kt:43)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2995)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:523)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchViewCreated(FragmentManager.java:2777)
at androidx.fragment.app.Fragment.performViewCreated(Fragment.java:3020)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:551)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:261)
at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1374)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2841)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:2784)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:262)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:478)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1435)
at android.app.Activity.performStart(Activity.java:8018)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3475)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2022-04-03 18:25:23.849 4959-4975/com.example.mvvmretrofit W/System: A resource failed to call close.
AlbumListFragment:
class AlbumListFragment : Fragment() {
private val viewModel: AlbumsViewModel by lazy {
ViewModelProvider(this)[AlbumsViewModel::class.java]
}
/**
* Inflates the layout with Data Binding, sets its lifecycle owner to the OverviewFragment
* to enable Data Binding to observe LiveData, and sets up the RecyclerView with an adapter.
*/
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val binding = FragmentAlbumListBinding.inflate(inflater)
binding.viewModel = viewModel
// Allows Data Binding to Observe LiveData with the lifecycle of this Fragment
binding.lifecycleOwner = this
// Giving the binding access to the OverviewViewModel
binding.viewModel = viewModel
setHasOptionsMenu(true)
return binding.root
}
/**
* Inflates the overflow menu that contains filtering options.
*/
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.overflow_menu, menu)
super.onCreateOptionsMenu(menu, inflater)
}
}
AlbumsViewModel.kt:
class AlbumsViewModel(val application: MyApplication) : AndroidViewModel(application) {
private val _response = MutableLiveData<String>()
val response: LiveData<String>
get() = _response
/**
* Call getMarsRealEstateProperties() on init so we can display status immediately.
*/
init {
getAlbumProperties()
}
/**
* Sets the value of the status LiveData to the Mars API status.
*/
private fun getAlbumProperties() {
AlbumApi.retrofitService.getAllAlbums().enqueue(object: Callback<List<Album>> {
override fun onResponse(call: Call<List<Album>>, response: Response<List<Album>>) {
_response.value = "Success: ${response.body()?.size} Album properties retrieved"
}
override fun onFailure(call: Call<List<Album>>, t: Throwable) {
_response.value = "Failure: " t.message
}
})
_response.value = "Set the Album API Response here!"
}
}
CodePudding user response:
The real error is the one listed lower down
Caused by: java.lang.NoSuchMethodException: com.example.retrotest.ui.AlbumsViewModel.<init> [class android.app.Application]
This error is because your ViewModel has a non-standard constructor (uses your custom MyApplication
instead of the default Application
argument) and the provider factory can't find the constructor it is looking for.
You need to change
AlbumsViewModel(val application: MyApplication)
to
AlbumsViewModel(val application: Application)
to get it to work.
If you actually need an instance of MyApplication
in your ViewModel somwewhere you can always get it by having it cast from the base class like this:
val myapp = getApplication<MyApplication>()