【问题标题】:How to implement databinding with Reflection in BaseFragment()如何在 BaseFragment() 中使用反射实现数据绑定
【发布时间】:2020-11-02 17:14:02
【问题描述】:

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

例如我有这个 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 中再次定义绑定类

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 的片段中的绑定

我想要的是这样的东西

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

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

我听说我应该使用反射,但我不确定如何完成它

【问题讨论】:

    标签: android kotlin android-fragments reflection fragment


    【解决方案1】:

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

    • 反射很慢
    • 这让事情变得比实际更复杂。

    您可以执行以下操作,而不是使用反射创造魔法:

    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 等内容):

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

    如果这对你有用,请告诉我。

    干杯

    【讨论】:

    • 有没有办法阻止我自己进行绑定并将其委托给 basefragment ?
    • 你到底是什么意思?你不需要对绑定做任何事情,你只需告诉你的 basefragment 你需要哪个绑定类。其他一切都可以在 basefragment 中完成
    • 是的,但是我如何通过绑定类?因为命名取决于布局名称+绑定
    • 当您将&lt;layout&gt; &lt;/layout&gt; 添加到您的layout.xml 时,会自动创建BindingClass。例如,如果布局名称为rebuild_list_item.xml,则绑定类为RebuildListItemBinding。这个类可以从任何地方访问,你可以很容易地将它传递给 baseFragment。如果该类不可用和/或添加所需的依赖项,也许 rebuild 您的项目。
    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 2013-05-05
    • 1970-01-01
    • 2019-06-03
    相关资源
    最近更新 更多