我在应用程序中有一个通用模式,其中每个Fragment
使用数据绑定和一个ViewModel
。理想情况下,我想在BaseFragment
中设置这两个组件。
在尝试执行此操作时,我遇到了两个问题:
viewModelClass()
类型的地方拥有抽象函数ViewModel
似乎是多余的。有没有办法重构它以确定ViewModel
中的BaseFragment
类型?我尝试用viewModel::class.java
或viewModel.javaClass
替换函数调用,但是由于viewModel
尚未初始化,因此这些功能不起作用。
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>