【问题标题】:ViewModelProvider is causing the crash as soon as fragment is opened. How do I resolve this?一旦打开片段,ViewModelProvider 就会导致崩溃。我该如何解决这个问题?
【发布时间】:2020-12-12 13:36:15
【问题描述】:

我正在使用 Room Database 制作笔记应用程序,但 AddFragment.kt 中的行 noteViewModel = ViewModelProvider(this).get(NoteViewModel::class.java) 正在使我的应用程序在打开 AddFragment 后立即崩溃。要查看完整代码,请在最后找到 github 存储库链接。

下面是 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$4.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$4.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$4.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 链接: Click Here

【问题讨论】:

  • ViewModelProvider(requireActivity()).get(NoteViewModel::class.java)
  • 抱歉,应用仍然崩溃。

标签: android kotlin android-room mobile-application android-mvvm


【解决方案1】:

你真正的错误是Caused by: java.lang.RuntimeException: cannot find implementation for com.example.notezy.Database.NoteDatabase,你应该修复它:

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

快乐编码

【讨论】:

  • 像魅力一样工作。非常感谢。
【解决方案2】:

理论上,ViewModels (VM) 可以通过 viewmodels() 使用 Kotlin 扩展库导入 androidx.fragment.app.viewModels 方法初始化为类级实例变量。通过将 VM 初始化为类级别的实例 var,它可以在类中访问。

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
    }

【讨论】:

  • 崩溃停止,但不会将数据插入数据库。
【解决方案3】:

除了在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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-31
    • 2018-08-06
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 2016-01-25
    • 1970-01-01
    相关资源
    最近更新 更多