MVVM框架搭建

题外

Jetpack中是有一个ViewModel的,但是并不是MVVM中的ViewModel,它的本意似乎是一个用于保存Activity中的临时数据,避免在屏幕旋转中丢失,然后顺带有Jetpack中的核心,关于Life周期的处理。
但是虽然说不是指定用于MVVM架构,但是使用MVVM架构中的ViewModel用它是非常方便的!
因为本来ViewModel就是用来提供数据的绑定的嘛

然后现在刚好在搭建项目,所以记录下具体的搭建方法
参考资料:https://github.com/manas-chaudhari/android-mvvm

绑定Activity的VM 和 layout

解决办法:

1、想想平常我们是怎么绑定的

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);
   User user = new User("Test", "User");
   binding.setUser(user);
}

2、抽象到基类之后,如何绑定的问题:

1、获得一个binging Class,绑定了类和XML

你看啊,我们不是没有一般的

setContentView(R.layout.activity_main);

这个语句了嘛,现在用怎么绑定activity和XML文件呢?就是:

MainActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.main_activity);

MainActivityBinding,我们知道这个binding类的名字是从Activity的对应layout的名字来的。那么我一个基类,怎么对应呢?
基类activity,就用父类的binding Class嘛,只要用上作为父类的bindingClass,java会自动帮我们转换的。
那么我们的各个binding Class的父类是什么呢?那就是:ViewDataBinding
来看官方文档:https://developer.android.com/reference/android/databinding/ViewDataBinding

2、binding绑定实体类,使用的方法
为什么要动态绑定

好的,我们现在有了正确的bindingClass,用它我们就能让Activity找到它自己对应的XML。但是我还需要把正确的实体类绑定在这个bindingClass上啊,不然怎么提供正确的数据?也就是:

binding.setUser(user);

我们知道这个setUser方法,是根据你的XML中定义来的,

 <data>
   <variable name="user" type="com.example.User"/>
 </data>

但是我抽象到父类上,怎么弄啊?又不能一一对应每个data的名字。但是你想,dataBinding框架既然能根据定义的变量名字提供对应的方法,那肯定能得到对应的变量的名称对吧
想一想,而我们需要的绑定条件是:变量名、bindingClass、实体类。这三个我们都能取得,那么能够进行动态绑定了嘛?

有时候,我们无法知道确切的binding类,比如RecyclerView Adapter可以使用任意的layout,
所以我们的binding类需要动态生成。
我们需要在onBindViewHolder方法中给变量赋值,比如我们的layout中声明了一个item变量,
我们通过BindingHolder的getBinding返回一个binding对象,调用setVariable方法给item变量赋值
参考:https://appkfz.com/2015/07/09/android-data-binding-3/

有点让人看不懂哈,所以我来翻译一下:RecyclerView的每个item的值,是由itemList的位置提供的,也就是items.get(position)。它的每个Item的Layout也可以是各不相同的,咋整呢?动态绑定的方法:

在onBindViewHolder()方法里,
利用DataBinding动态绑定ViewDataBinding.setVariable(BR.itemP, ItemPresenter);为每个Item设置点击事件。
同时,数据也是同样在里面绑定的:setVariable(BR.data, mDatas.get(position))。
参考:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2016/1214/6857.html

另外这个BR是个啥,
BR.java:这个文件主要是给我们在XML文件中每个标签设置的variable以及被Bindable注解的属性添加一个静态的int类型的索引,在以后对这些variable进行操作的时候都可以使用这个索引id作为参数。
也就是:上面的user变量的这个variable标签
参考:https://juejin.im/post/58400839ac502e006cbd0f31#heading-14

 <data>
   <variable name="user" type="com.example.User"/>
 </data>
完成动态绑定

所以我们这里的父类也是一样,用这种动态绑定的方法来完成。

        binding = DataBindingUtil.setContentView(this, getLayoutId());
        Preconditions.checkNotNull(binding, "bindingClass in " + MvvmActivity.this.getClass().getSimpleName());
        binding.setVariable(BR.vm, createViewModel());
在其他地方的动态绑定

但是,我们之前也说了,在使用RecyclerView的时候,我们也需要动态绑定,可惜RecyclerViewAdapter并不知道activity、layout,所以我们需要多来一层,使用一个ViewModelBinder,以后把这个ViewHolderBindre传入Adapter中就可以了

public interface ViewModelBinder {
    void bind(ViewDataBinding viewDataBinding, ViewModel viewModel);
}
/*
通过完成这个bind方法,以后我们在activity中对RecyclerViewAdapter传入getDefaultBinder()方法,就可以得到每个
不同的activity的Binder了。
*/
@NonNull
public static final ViewModelBinder defaultBinder = new ViewModelBinder() {
    @Override
    public void bind(ViewDataBinding viewDataBinding, ViewModel viewModel) {
        viewDataBinding.setVariable(BR.vm, viewModel);
    }
};
    private ViewDataBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, getLayoutId());


        getDefaultBinder().bind(binding, createViewModel());
    }

ViewModel传递消息

思路:一切无法在这个类本身持有的引用、完成的api调用,都可以通过传递一个控制器来解决。
ViewModel传递消息就是这样,ViewModel不应该持有Activity的引用,所以我们在构建自己的ViewModel的时候,可以通过构造函数传递一个Navigator类,用这个类来完成跳转

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值