问题
I have a ParentFragment
and a ChildFragment
. They are working pretty fine.
My problem is that in the future I might create many child fragments and this makes me write this boilerplate code for every single child fragment. Thus, I would like to optimize my ParentFragment
so that I do not have to write boilerplate code for every single new child framment I create in the future.
ParentFragment
abstract class ParentFragment<T: ViewDataBinding>: Fragment() {
@LayoutRes
abstract fun getLayoutResId(): Int
protected lateinit var binding: T
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
super.onCreateView(inflater, container, savedInstanceState)
return DataBindingUtil.inflate<T>(inflater, getLayoutResId(), container, false).apply { binding = this }.root
}
ChildFragment
class ChildFragment: ParentFragment<FragmentChildBinding>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//THIS IS THE BOILERPLATE METHOD I AM TALKING ABOUT.
//I WOULD LIKE TO MOVE THIS CODE IN THE PARENTFRAGMENT
initBinding()
}
@LayoutRes
override fun getLayoutResId() = R.layout.fragment_child
fun initBinding() {
val viewModel: ChildViewModel = getViewModel() //This method is from Koin
binding.viewModel = viewModel
binding.lifecycleOwner = this
}
I tried to move this initBinding
method code into ParentFragment
but I got errors. Any suggestions would be greatly appreciated.
回答1:
So, your current issue is that you want to make your initBinding()
function common in such a way that all child fragment can access it.
Now issue is that logic inside initBinding
comes with koin dependency that gets resolved dynamically. So, each child fragment may have different ViewModel instance.
There is one way you can resolve this problem:
Take your ViewModel
object as method parameter so that you can inject it from your child fragment while having method in parent fragment. check out below how:
initBinding()
Method in ParentFragment
with viewModel
as method parameter that we will pass on from child fragments.
abstract class ParentFragment<T: ViewDataBinding>: Fragment() {
// Other stuffs removed for sack of simplicity
protected fun initBinding(viewModel: ViewModel) {
binding.viewModel = viewModel
binding.lifecycleOwner = this
}
}
Accessing it from ChildFragment
:
class ChildFragment: ParentFragment<FragmentChildBinding>() {
// Other stuffs removed for sack of simplicity
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// THIS IS HOW YOU CAN CONSUME THIS METHOD
initBinding(getViewModel())
}
}
回答2:
You need to call serVariable() on your binding
object to set ViewModel
in the parent Fragment. Optionally in your parent Fragment you can get ViewModel through abstract function if child Fragments have their own ViewModels.
You can follow this post to solve your problem.
来源:https://stackoverflow.com/questions/59279430/optimizing-parent-fragment-for-viewmodel-and-databinding-in-order-to-avoid-boile