I started using ViewBinding. After searching for some example or advice how to use ViewBinding with an abstract base class that should handle same logic on views expected to be present in every child's layout, I endet up posting this question here.
Scenario:
I have a base class public abstract class BaseFragment
. There are multiple Fragments that extend this base class. These Fragments have common views that are handled from the base class implementation (with the "old" findViewById()
). For example every fragment's layout is expected to contain a TextView with ID text_title. Here's how it's handled from the BaseFragment
's onViewCreated()
:
TextView title = view.findViewById(R.id.text_title);
// Do something with the view from the base class
Now the ViewBinding-API generates binding-classes for each child-Fragment. I can reference the views using the binding. But I can't using the concrete Bindings from the base class. Even with introducing generics to the base class there are too many types of fragment-bindings that I discarded this solution for now.
What's the recommended way of handling the binding's views from the abstract base class? Are there any best-practices? Didn't found a built-in mechanism in the API to handle this scenario in an elegant way.
When the child-fragments are expected to contain common views, I could provide abstract methods that return the views from the concrete bindings of the Fragments and make them accessible from the base class. (For example protected abstract TextView getTitleView();
). But is this an advantage rather than using findViewById()
? What do you think? Any other (better) solutions? Please let's start some discuss.
Hi I have created a blog post which covers view-binding in-depth, and also includes both composition patter/delegate pattern to implement view binding as well as using inheritance checkout from the link
checkout for complete code of BaseActivity
and BaseFragment
along with usage
/*
* In Activity
* source : https://chetangupta.net/viewbinding/
* Author : ChetanGupta.net
*/
abstract class ViewBindingActivity<VB : ViewBinding> : AppCompatActivity() {
private var _binding: ViewBinding? = null
abstract val bindingInflater: (LayoutInflater) -> VB
@Suppress("UNCHECKED_CAST")
protected val binding: VB
get() = _binding as VB
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
_binding = bindingInflater.invoke(layoutInflater)
setContentView(requireNotNull(_binding).root)
setup()
}
abstract fun setup()
override fun onDestroy() {
super.onDestroy()
_binding = null
}
}
/*
* In Fragment
* source : https://chetangupta.net/viewbinding/
* Author : ChetanGupta.net
*/
abstract class ViewBindingFragment<VB : ViewBinding> : Fragment() {
private var _binding: ViewBinding? = null
abstract val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> VB
@Suppress("UNCHECKED_CAST")
protected val binding: VB
get() = _binding as VB
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = bindingInflater.invoke(inflater, container, false)
return requireNotNull(_binding).root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setup()
}
abstract fun setup()
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
For usage, advance pattern and antipattern checkout blog Androidbites|ViewBinding