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 尚未在运行时初始化。我该如何解决这个问题?
- 在片段中初始化会起作用
- 如果你们给我提供一个从parent初始化的viewmodel就更好了,parent是一个activity
如果你想在 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>
....
我正在尝试使用 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 尚未在运行时初始化。我该如何解决这个问题?
- 在片段中初始化会起作用
- 如果你们给我提供一个从parent初始化的viewmodel就更好了,parent是一个activity
如果你想在 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>
....