使用数据绑定和ViewModel优化BaseFragment?

时间:2019-05-28 22:13:22

标签: android kotlin android-databinding android-viewmodel

我在应用程序中有一个通用模式,其中每个Fragment使用数据绑定和一个ViewModel。理想情况下,我想在BaseFragment中设置这两个组件。

在尝试执行此操作时,我遇到了两个问题:

  1. 在子类提供其viewModelClass()类型的地方拥有抽象函数ViewModel似乎是多余的。有没有办法重构它以确定ViewModel中的BaseFragment类型?

我尝试用viewModel::class.javaviewModel.javaClass替换函数调用,但是由于viewModel尚未初始化,因此这些功能不起作用。

  1. 更严重的问题:BaseFragment的每个子类都有一个名为viewModel的数据绑定变量。通常,我可以直接通过binding.viewModel设置此变量。但是,如果要在BaseFragment中设置此变量,则必须通过名为BR的生成的类来访问它,该类包含数据绑定变量的ID。

这是通过binding.setVariable(BR.viewModel, viewModel)完成的。由于尝试从BR访问BaseFragment会产生构建错误,因此我尝试让子类通过抽象函数bindingVariable()提供它。最后,这会产生相同的构建错误,其中BR无法解决。

感谢您对这些问题的见解。

BaseFragment.kt

abstract class BaseFragment<B: ViewDataBinding, VM: ViewModel> : Fragment() {

    private lateinit var binding: B
    private lateinit var viewModel: VM

    /**
     * Layout to inflate
     */
    @LayoutRes
    abstract fun layoutResId(): Int

    /**
     * View model class to instantiate
     */
    abstract fun viewModelClass(): Class<VM>

    /**
     * viewModel data binding variable
     */
    abstract fun bindingVariable(): Int

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {

        binding = DataBindingUtil.inflate(
                inflater,
                layoutResId(),
                container,
                false
        )

        // Issue 1: Can I refactor this to eliminate viewModelClass() function?
        viewModel = ViewModelProviders
                .of(this)
                .get(viewModelClass())

        // Issue 2: Can't access generated BR class to set "viewModel" variable
        binding.setVariable(bindingVariable(), viewModel)

        return binding.root
    }
}

SubFragment.kt

class SubFragment : BaseFragment<SubBinding, SubViewModel>() {

    override fun layoutResId() = R.layout.fragment_sub

    override fun viewModelClass() = SubViewModel::class.java

    // build error: can't resolve symbol BR
    override fun bindingVariable() = BR.viewModel
}

fragment_sub.xml

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="SubFragment">

    <data class="SubBinding">

        <variable
            name="viewModel"
            type="com.user.app.SubViewModel"/>

    </data>

    <!-- rest of layout -->

</layout>

0 个答案:

没有答案