片段一打开,ViewModelProvider 就会导致崩溃。我该如何解决这个问题?
ViewModelProvider is causing the crash as soon as fragment is opened. How do I resolve this?
我正在使用 Room Database 制作一个笔记应用程序,但是 AddFragment.kt
中的行 noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
让我的应用程序在 AddFragment
打开后立即崩溃。要查看完整代码,请在最后找到 github 存储库 link。
下面是 AddFragment.kt
的完整代码
class AddFragment : Fragment() {
private lateinit var binding: FragmentAddBinding
private lateinit var noteViewModel: NoteViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_add, container, false)
//throwing error
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
binding.addBtn.setOnClickListener {
val noteTitle: String = binding.addTitleText.text.toString().trim()
val noteBody: String = binding.addNoteText.text.toString().trim()
when {
noteTitle.isEmpty() -> {
Toast.makeText(this.activity, "Title missing.", Toast.LENGTH_SHORT).show()
binding.addTitleText.requestFocus()
return@setOnClickListener
}
noteBody.isEmpty() -> {
Toast.makeText(this.activity, "Note Body missing.", Toast.LENGTH_SHORT).show()
binding.addNoteText.requestFocus()
return@setOnClickListener
}
else -> {
noteViewModel.insertNote(Note(noteTitle, noteBody))
Toast.makeText(this.activity, "New Note Added.", Toast.LENGTH_SHORT).show()
}
}
}
return binding.root
}
崩溃报告
java.lang.RuntimeException: Cannot create an instance of class com.example.notezy.ViewModel.NoteViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:275)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.notezy.Fragments.AddFragment.onCreateView(AddFragment.kt:33)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.notezy.Fragments.AddFragment.onCreateView(AddFragment.kt:33)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.RuntimeException: cannot find implementation for com.example.notezy.Database.NoteDatabase. NoteDatabase_Impl does not exist
at androidx.room.Room.getGeneratedImplementation(Room.java:94)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:952)
at com.example.notezy.Database.NoteDatabase$Companion.getDatabase(NoteDatabase.kt:24)
at com.example.notezy.ViewModel.NoteViewModel.<init>(NoteViewModel.kt:18)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.notezy.Fragments.AddFragment.onCreateView(AddFragment.kt:33)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Github Link 回购: Click Here
ViewModels (VM) 理论上可以通过 viewmodels() 使用 Kotlin 扩展库导入 androidx.fragment.app.viewModels 方法初始化为 class 级实例变量。通过将 VM 初始化为 class 级实例变量,可以在 class.
中访问它
class AddFragment : Fragment() {
private lateinit var binding: FragmentAddBinding
//private lateinit var noteViewModel: NoteViewModel
private val noteViewModel: NoteViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_add, container, false)
//throwing error
//noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
binding.addBtn.setOnClickListener {
val noteTitle: String = binding.addTitleText.text.toString().trim()
val noteBody: String = binding.addNoteText.text.toString().trim()
when {
noteTitle.isEmpty() -> {
Toast.makeText(this.activity, "Title missing.", Toast.LENGTH_SHORT).show()
binding.addTitleText.requestFocus()
return@setOnClickListener
}
noteBody.isEmpty() -> {
Toast.makeText(this.activity, "Note Body missing.", Toast.LENGTH_SHORT).show()
binding.addNoteText.requestFocus()
return@setOnClickListener
}
else -> {
noteViewModel.insertNote(Note(noteTitle, noteBody))
Toast.makeText(this.activity, "New Note Added.", Toast.LENGTH_SHORT).show()
}
}
}
return binding.root
}
除了在 onCreateView
中夸大您的视图外,不要做任何事情。将视图设置和视图模型使用移动到 onViewCreated
.
事实上,Fragment 的构造函数允许您直接传递布局 ID,因此您根本不必重写 onCreateView
。您可以将绑定工厂方法从 inflate
切换到 bind
以附加到已经膨胀的视图。
class AddFragment : Fragment(R.layout.fragment_add) {
private lateinit var binding: FragmentAddBinding
private lateinit var noteViewModel: NoteViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = DataBindingUtil.bind(view)
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
binding.addBtn.setOnClickListener {
// ...
}
return binding.root
}
}
你真正的错误是Caused by: java.lang.RuntimeException: cannot find implementation for com.example.notezy.Database.NoteDatabase
,要修正它你应该:
- 将
id 'kotlin-kapt'
添加到 build.gradle
中的插件
- 添加
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
依赖
- 将
annotationProcessor
替换为 kapt
注释 "androidx.room:room-compiler:$rootProject.roomVersion"
dependency
编码愉快
我正在使用 Room Database 制作一个笔记应用程序,但是 AddFragment.kt
中的行 noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
让我的应用程序在 AddFragment
打开后立即崩溃。要查看完整代码,请在最后找到 github 存储库 link。
下面是 AddFragment.kt
的完整代码class AddFragment : Fragment() {
private lateinit var binding: FragmentAddBinding
private lateinit var noteViewModel: NoteViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_add, container, false)
//throwing error
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
binding.addBtn.setOnClickListener {
val noteTitle: String = binding.addTitleText.text.toString().trim()
val noteBody: String = binding.addNoteText.text.toString().trim()
when {
noteTitle.isEmpty() -> {
Toast.makeText(this.activity, "Title missing.", Toast.LENGTH_SHORT).show()
binding.addTitleText.requestFocus()
return@setOnClickListener
}
noteBody.isEmpty() -> {
Toast.makeText(this.activity, "Note Body missing.", Toast.LENGTH_SHORT).show()
binding.addNoteText.requestFocus()
return@setOnClickListener
}
else -> {
noteViewModel.insertNote(Note(noteTitle, noteBody))
Toast.makeText(this.activity, "New Note Added.", Toast.LENGTH_SHORT).show()
}
}
}
return binding.root
}
崩溃报告
java.lang.RuntimeException: Cannot create an instance of class com.example.notezy.ViewModel.NoteViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:275)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.notezy.Fragments.AddFragment.onCreateView(AddFragment.kt:33)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.notezy.Fragments.AddFragment.onCreateView(AddFragment.kt:33)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.RuntimeException: cannot find implementation for com.example.notezy.Database.NoteDatabase. NoteDatabase_Impl does not exist
at androidx.room.Room.getGeneratedImplementation(Room.java:94)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:952)
at com.example.notezy.Database.NoteDatabase$Companion.getDatabase(NoteDatabase.kt:24)
at com.example.notezy.ViewModel.NoteViewModel.<init>(NoteViewModel.kt:18)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.notezy.Fragments.AddFragment.onCreateView(AddFragment.kt:33)
at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2698)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:320)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1187)
at androidx.fragment.app.FragmentManager.addAddedFragments(FragmentManager.java:2224)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1997)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1953)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1849)
at androidx.fragment.app.FragmentManager.run(FragmentManager.java:413)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Github Link 回购: Click Here
ViewModels (VM) 理论上可以通过 viewmodels() 使用 Kotlin 扩展库导入 androidx.fragment.app.viewModels 方法初始化为 class 级实例变量。通过将 VM 初始化为 class 级实例变量,可以在 class.
中访问它class AddFragment : Fragment() {
private lateinit var binding: FragmentAddBinding
//private lateinit var noteViewModel: NoteViewModel
private val noteViewModel: NoteViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_add, container, false)
//throwing error
//noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
binding.addBtn.setOnClickListener {
val noteTitle: String = binding.addTitleText.text.toString().trim()
val noteBody: String = binding.addNoteText.text.toString().trim()
when {
noteTitle.isEmpty() -> {
Toast.makeText(this.activity, "Title missing.", Toast.LENGTH_SHORT).show()
binding.addTitleText.requestFocus()
return@setOnClickListener
}
noteBody.isEmpty() -> {
Toast.makeText(this.activity, "Note Body missing.", Toast.LENGTH_SHORT).show()
binding.addNoteText.requestFocus()
return@setOnClickListener
}
else -> {
noteViewModel.insertNote(Note(noteTitle, noteBody))
Toast.makeText(this.activity, "New Note Added.", Toast.LENGTH_SHORT).show()
}
}
}
return binding.root
}
除了在 onCreateView
中夸大您的视图外,不要做任何事情。将视图设置和视图模型使用移动到 onViewCreated
.
事实上,Fragment 的构造函数允许您直接传递布局 ID,因此您根本不必重写 onCreateView
。您可以将绑定工厂方法从 inflate
切换到 bind
以附加到已经膨胀的视图。
class AddFragment : Fragment(R.layout.fragment_add) {
private lateinit var binding: FragmentAddBinding
private lateinit var noteViewModel: NoteViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = DataBindingUtil.bind(view)
noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java)
binding.addBtn.setOnClickListener {
// ...
}
return binding.root
}
}
你真正的错误是Caused by: java.lang.RuntimeException: cannot find implementation for com.example.notezy.Database.NoteDatabase
,要修正它你应该:
- 将
id 'kotlin-kapt'
添加到build.gradle
中的插件
- 添加
implementation "androidx.room:room-ktx:$rootProject.roomVersion"
依赖 - 将
annotationProcessor
替换为kapt
注释"androidx.room:room-compiler:$rootProject.roomVersion"
dependency
编码愉快