如何在BaseFragment()中使用反射实现数据绑定 [英] How to implement databinding with Reflection in BaseFragment()

查看:156
本文介绍了如何在BaseFragment()中使用反射实现数据绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个BaseFragment,在其中我将在其上传递布局资源,并且它应该输出绑定以在片段本身中工作,而不是每次扩展该片段时都需要这样做.

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.

例如,我有这个BaseFragment

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)
    }
...

我在其中使用这种方式

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

现在,如果我使用它,我将需要在我的onCreateView中再次进行绑定类的定义

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
 }

}

我要实现的是,因为我将布局传递给BaseFragment,所以我希望我的BaseFragment处理绑定的创建,并只将用于扩展BaseFragment的片段中的绑定返回给我

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 = ""
    }
 }

所以我的问题是,如何在BaseFragment内部实现onDestroy()和onCreateView,以始终从传入的布局中为我创建绑定?

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

推荐答案

我没有听说过仅从布局中获取数据绑定的可能性,但是即使有可能,我也不认为这是推荐的方法,原因有两个:

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:

  • 反射很慢
  • 这使事情变得比原来更复杂.

您可以执行以下操作,而不是通过反射制作魔术:

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.
    }

然后,当您仍然需要bindingProperty时,我建议使用以下库(它处理所有onDestoryView内容等):

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'

然后您可以像这样使用

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.

欢呼

这篇关于如何在BaseFragment()中使用反射实现数据绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆