How to implement databinding with Reflection in BaseFragment()

∥☆過路亽.° 提交于 2020-12-15 06:32:15

问题


I'm trying to implement a BaseFragment in which I will pass the layout resource on it and it should outputs the binding to work in the fragment itself instead of need to do it everytime the fragment is extended.

For example I have this BaseFragment

open class BaseFragment(@LayoutRes contentLayoutId : Int = 0) : Fragment(contentLayoutId) {

    private lateinit var onInteractionListener: OnFragmentInteractionListener

    val toolbar : Toolbar?
        get() {
            return if(activity is BaseActivity)
                (activity as BaseActivity).toolbar
            else
                null
        }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        setOnInteractionListener(context)
    }
...

In which I use like this

class A(): BaseFragment(R.layout.myFragment) { ... }

Now, if I use this I will need to do the definition of the binding class again in my onCreateView

class A(): BaseFragment(R.layout.myFragment) { 

private lateinit var binding: MyFragmentBinding

 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        binding = DataBindingUtil.inflate(inflater, R.layout.myFragment, container, false)
        return binding.root
    }

 override fun onDestroy(){
  binding = null
 }

}

What I want to implement is that since I'm passwing the layout to my BaseFragment, I want my BaseFragment to handle the creation of the binding and just return me the binding in the fragment which I use to extend BaseFragment

What I want to have is something like this

class A(): BaseFragment(R.layout.myFragment) { 
    
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.myTextView = ""
    }
 }

So my question is, how I can implement inside BaseFragment the onDestroy() and the onCreateView to always create a binding for me from the layout I'm passing in ?

I heard that I should use reflection but I'm not that sure on how to accomplish it


回答1:


I didn't hear about the possibility to get the databinding just from a layout, but even if it's possible, I don't think that is the recommended way, because of two reasons:

  • Reflection is slow
  • It makes things more complicated than they are.

Instead of making magic with Reflection, you could do something like this:

abstract class BaseFragment<out VB: ViewDataBinding>(
    private val layout: Int,
    // Other Dependencies if wanted
) : Fragment() {
    abstract val viewModel: ViewModel
    // other variables that all fragments need
    
    // This does not cause any memory leak, because you are not storing the binding property.
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? = DataBindingUtil.inflate<VB>(inflater, layout, container, false).apply {
        lifecycleOwner = viewLifecycleOwner
        setVariable(BR.viewModel, viewModel)
    }.root
}

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
       // Do some basic work here that all fragments need
       // like a progressbar that all fragments share, or a button, toolbar etc.
    }

And then, when you still need the bindingProperty, I would suggest the following library (it handles all the onDestoryView stuff etc):

implementation 'com.kirich1409.viewbindingpropertydelegate:viewbindingpropertydelegate:1.2.2'

You can then use this like:

class YourFragment(yourLayout: Int) : BaseFragment<YourBindingClass>() {
     private val yourBinding: YourBindingClass by viewBinding()
     override val viewModel: YourViewModel by viewModels()

     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        // do binding stuff
     }
}

Let me know if this worked for you.

Cheers



来源:https://stackoverflow.com/questions/64650150/how-to-implement-databinding-with-reflection-in-basefragment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!