片段一打开,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,要修正它你应该:

  1. id 'kotlin-kapt' 添加到 build.gradle
  2. 中的插件
  3. 添加implementation "androidx.room:room-ktx:$rootProject.roomVersion"依赖
  4. annotationProcessor 替换为 kapt 注释 "androidx.room:room-compiler:$rootProject.roomVersion" dependency

编码愉快