Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm trying to implement data-binding in android with kotlin:
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
But it says lateinit property viewModel has not been initialized on runtime. How can I resolve this ?
Initializing in fragment will work
It will better if you guys provide me with viewmodel initialized from parent, parent is an activity
If You want to init viewModel in Activity and use it in fragment You can do it in this way:
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
properties require you to initialize them before the first use. The error happens only if it wasn't initialized. You can check if lateinit
is initialized by using isInitialized
property of KProperty0
interface.
val isReadyForUse = ::viewModel.isInitialized
Inside of a Fragment
you can initialize a ViewModel
using extension function viewModels()
:
import androidx.fragment.app.viewModels
class YourFragment: Fragment {
private val viewModel: YourViewModel by viewModels()
It's lazy-loaded, which means as soon as you'll try to access viewModel
it will be initialized and returned. Next time no initialization will happen.
If you want to make your ViewModel
class loaded in an Activity
first and later in a Fragment
use activityViewModels()
.
Note: after the first initialization of a ViewModel
by activityViewModels()
it will be stored in a ViewModelStore
that is owned by Activity
. To create new instance of a YourViewModel
by using activityViewModels()
you will have to finish your Activity
or clear view model store requireActivity().viewModelStore.clear()
.
To initialize in an Activity and use a Fragment do next:
class YourActivity {
override fun onCreate(savedInstanceState: Bundle?) {
val viewModelInit = ViewModelProvider(this).get(YourViewModel.javaClass)
And in a Fragment
:
import androidx.fragment.app.activityViewModels
class YourFragment: Fragment {
private val viewModel: YourViewModel by activityViewModels()
Here is the thing worked for me :
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
In 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">
<variable
name="login"
type="com........." />
</data>
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.