【问题标题】:Optimizing Parent Fragment for ViewModel and DataBinding in order to avoid boilerplate code优化 ViewModel 和 DataBinding 的父片段以避免样板代码
【发布时间】:2019-12-11 15:42:29
【问题描述】:

我有一个ParentFragment 和一个ChildFragment。他们工作得很好。

我的问题是,将来我可能会创建许多子片段,这使我为每个子片段编写此样板代码。因此,我想优化我的ParentFragment,这样我就不必为将来创建的每个新子框架编写样板代码。

ParentFragment

abstract class ParentFragment<T: ViewDataBinding>: Fragment() {

    @LayoutRes
    abstract fun getLayoutResId(): Int

    protected lateinit var binding: T

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

        return DataBindingUtil.inflate<T>(inflater, getLayoutResId(), container, false).apply { binding = this }.root
    }

ChildFragment

class ChildFragment: ParentFragment<FragmentChildBinding>() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //THIS IS THE BOILERPLATE METHOD I AM TALKING ABOUT. 
        //I WOULD LIKE TO MOVE THIS CODE IN THE PARENTFRAGMENT
        initBinding() 
    }

    @LayoutRes
    override fun getLayoutResId() = R.layout.fragment_child

    fun initBinding() {
        val viewModel: ChildViewModel = getViewModel() //This method is from Koin
        binding.viewModel = viewModel
        binding.lifecycleOwner = this
    }

我尝试将此 initBinding 方法代码移动到 ParentFragment 中,但出现错误。任何建议将不胜感激。

【问题讨论】:

    标签: android fragment android-databinding android-viewmodel koin


    【解决方案1】:

    因此,您当前的问题是您希望使您的 initBinding() 函数通用,以便所有子片段都可以访问它。

    现在的问题是 initBinding 内部的逻辑带有动态解析的 koin 依赖项。因此,每个子 Fragment 可能有不同的 ViewModel 实例。


    有一种方法可以解决此问题:

    将您的ViewModel 对象作为方法参数,以便您可以从子片段中注入它,同时在父片段中有方法。看看下面的方法:

    initBinding()ParentFragment 中的方法,viewModel 作为方法参数,我们将从子片段传递。

    abstract class ParentFragment<T: ViewDataBinding>: Fragment() {
    
        // Other stuffs removed for sack of simplicity
    
        protected fun initBinding(viewModel: ViewModel) {
            binding.viewModel = viewModel
            binding.lifecycleOwner = this
        }
    }
    

    ChildFragment访问它:

    class ChildFragment: ParentFragment<FragmentChildBinding>() {
    
        // Other stuffs removed for sack of simplicity
    
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    
            // THIS IS HOW YOU CAN CONSUME THIS METHOD
            initBinding(getViewModel()) 
        }
    }
    

    【讨论】:

    • 我无法访问binding.viewModel 变量。我认为,这是因为绑定还不知道它有一个名为viewModel 的字段。你怎么看?
    • 哦!,这显然是我完全错过的事情。那我再想个办法吧。
    【解决方案2】:

    您需要在您的binding 对象上调用serVariable() 以在父片段中设置ViewModel。如果子 Fragment 有自己的 ViewModel,则可以选择在您的父 Fragment 中通过抽象函数获取 ViewModel。

    您可以关注this post来解决您的问题。

    【讨论】:

    • 如果我这样做,代码运行良好,但我的data binding 不工作。更改 ViewModel 中的变量值不会在视图中更新。
    • 我将创建另一个问题并将链接发送到这里。因为我认为问题是独立的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 2010-11-14
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 1970-01-01
    相关资源
    最近更新 更多