android 片段视图模型初始化失败

android fragment viewmodel initialization failed

我正在尝试使用 kotlin 在 android 中实现数据绑定:

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mBinding = DataBindingUtil.inflate<ViewDataBinding>(
            inflater, R.layout.fragment_login, container, false
        ) as FragmentLoginBinding
        val view: View = mBinding.root
        mBinding.login?.invoke(viewModel)
        return view
    }

但它说 lateinit 属性 viewModel 尚未在运行时初始化。我该如何解决这个问题?

如果你想在 Activity 中初始化 viewModel 并在片段中使用它你可以这样做:

MainActvity.kt:

private lateinit var viewModel: MainActivityVM

override fun onCreate(savedInstanceState: Bundle?)
{
    viewModel = ViewModelProvider(this).get(MainActivityVM::class.java)

    super.onCreate(savedInstanceState)
}

YourFragment.kt:

private lateinit var binding: YourFragmentBinding
private lateinit var viewModel: MainActivityVM

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View?
{
    binding = DataBindingUtil.inflate(
        inflater,
        R.layout.fragment_your, container, false
    )

    binding.lifecycleOwner = this

    viewModel = ViewModelProvider(requireActivity()).get(MainActivityVM::class.java)

    //here You can use Your viewModel

    return binding.root
}

lateinit 属性要求您在首次使用前对其进行初始化。只有在未初始化时才会发生错误。您可以使用KProperty0 接口的isInitialized 属性 检查lateinit 是否被初始化。

val isReadyForUse = ::viewModel.isInitialized

Fragment 内部,您可以使用扩展函数 viewModels():

初始化 ViewModel
import androidx.fragment.app.viewModels

class YourFragment: Fragment {
    private val viewModel: YourViewModel by viewModels()
}

它是 lazy-loaded,这意味着只要您尝试访问 viewModel,它就会被初始化并返回。下次不会发生初始化。

如果你想让你的 ViewModel class 先在 Activity 中加载,然后在 Fragment 中加载,请使用 activityViewModels().

注意:activityViewModels() 首次初始化 ViewModel 后,它将存储在 Activity 拥有的 ViewModelStore 中。要使用 activityViewModels() 创建 YourViewModel 的新实例,您必须完成 Activity 或清除视图模型存储 requireActivity().viewModelStore.clear().

要在 Activity 中初始化并使用 Fragment,请执行以下操作:

class YourActivity {
    override fun onCreate(savedInstanceState: Bundle?) {
        val viewModelInit = ViewModelProvider(this).get(YourViewModel.javaClass)
    }
}

并且在 Fragment:

import androidx.fragment.app.activityViewModels

class YourFragment: Fragment {
    private val viewModel: YourViewModel by activityViewModels()
}

这是对我有用的东西:

mBinding = DataBindingUtil.inflate<ViewDataBinding>(
            inflater, R.layout.fragment_login, container, false
        ) as FragmentLoginBinding
        val view: View = mBinding.root
        viewModel = ViewModelProvider(requireActivity()).get(AuthViewModel::class.java)
        mBinding.login = viewModel
        return view

在XML中:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <variable
            name="login"
            type="com........." />
    </data>
    ....