Android片段ViewModel初始化失败

时间:2020-08-03 14:08:47

标签: android kotlin viewmodel android-viewmodel

我正在尝试使用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尚未在运行时初始化。我该如何解决?

  • 片段初始化会起作用
  • 如果你们为我提供从父级初始化的viewmodel,父级是一项活动,那会更好

3 个答案:

答案 0 :(得分:2)

如果要在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
}

答案 1 :(得分:1)

lateinit属性要求您在首次使用之前对其进行初始化。仅在未初始化的情况下才会发生错误。您可以使用lateinit界面的isInitialized属性来检查KProperty0是否已初始化。

val isReadyForUse = ::viewModel.isInitialized

Fragment内,您可以使用扩展功能ViewModel初始化viewModels()

import androidx.fragment.app.viewModels

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

它是延迟加载的,这意味着一旦您尝试访问viewModel,它将被初始化并返回。下次将不会进行初始化。

如果您想先将ViewModel类加载到Activity中,然后再加载到Fragment中,请使用activityViewModels()

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

要在活动中初始化并使用片段,请执行以下操作:

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()
}

答案 2 :(得分:0)

这是为我工作的东西:

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>
    ....