当你拿到别人的mvvm不会怎么办,看这里


这里只说拿着别人的mvvm怎么快速让自己进入开发状态,mvvm怎么搭建后面会详细说明,现在这个demo的架构里面可能有些没用的东西,不过也能拿着用,后面会把这套好好整理下再对每个点详细的进行说明(demo的github地址在文章末尾)。另外,


xml文件

注意点

①最外层的父布局必须是layout ,且这个父布局不能设置长宽属性,否则会膨胀
②data标签内的variable需要加这两个属性:
name:就是名字,任意写,作用是为了在Activity里作为标识给Activity绑定viewmodel
type:对应viewmodel的全路径,匹配好viewmodel之后,系统会自动生成这个xml文件的databinding
③data标签下面就是真正的布局,跟以往一样。

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    android:fitsSystemWindows="true"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="viewModel"
            type="com.sz.mangosteeneg.ui.viewmodel.TestMvvmViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
        。。。。。。

使用viewmodel简单的设置文本点击事件等

以TextView为例,
①text属性为android:text="@{viewModel.txt}"
viewmodel为data标签中name属性内容,调用了viewmodel类中的txt对象,viewmodel类中的写法在下面会介绍
②点击事件的xml设置android:onClick="@{viewModel.click}"
click为viewmodel中的方法。就是在xml文件中设置点击事件,只不过引用到了viewmodel中。

<TextView
            android:id="@+id/tv_t"
            android:onClick="@{viewModel.click}"
            android:text="@{viewModel.txt}"
            android:textSize="20sp"
            android:textColor="#333333"
            android:gravity="center"
            app:layout_constraintBottom_toBottomOf="parent"
            android:layout_width="match_parent"
            android:layout_height="40dp"/>

示例xml的全部代码

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    android:fitsSystemWindows="true"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="viewModel"
            type="com.sz.mangosteeneg.ui.viewmodel.TestMvvmViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rl"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintBottom_toTopOf="@+id/tv_t"
            android:layout_width="match_parent"
            android:layout_height="0dp"/>

        <TextView
            android:id="@+id/tv_t"
            android:onClick="@{viewModel.click}"
            android:text="@{viewModel.name}"
            android:textSize="20sp"
            android:textColor="#333333"
            android:gravity="center"
            app:layout_constraintBottom_toBottomOf="parent"
            android:layout_width="match_parent"
            android:layout_height="40dp"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>

viewmodel

*继承项目中的ViewModel的父类
viewmodel一般只进行数据的数理,除了处理数据别的最好啥都别干(当然,要是你对viewmodel了解非常深当我没说)。也最好不要吧对应Activity的对象(上下文)给塞过来。会造成内存泄漏

点击事件及文本改变

①文本改变
在viewmodel中声明一个容器对象,然后xml中设置好

//文本内容
    public ObservableField<String> txt = new ObservableField<>();

一般是在网络请求完成之后设置数据,调用set方法即可:txt.set(“…”);

//假装自己是个网络请求
    public void reqJiade(){
        List<String> list = new ArrayList<>();
        for(int i=0;i<200;i++){
            list.add("扫地欧尼"+i);
        }
        liveString.setValue(list);
        txt.set("文本改变");
    }

②点击事件,xml中用viewmodel调用这个方法即可,注意不用带()

//文本的点击事件
    public void click(View view){
        ToastUtils.showShort("文本被点击");
    }

livedata监听数据

livedata本质上是观察者模式。被观察者是数据的获取这个动作,并将获到的数据对象传递给观察者。
①声明数据要传递数据的类型的livedata,注意用public因为Activity还要用

public MutableLiveData<CityAreasBean> liveAddress = new MutableLiveData<>();
    public MutableLiveData<List<String>> liveString = new MutableLiveData<>();

②数据请求成功之后使用对应的livedata对象调用setValue()方法储存数据,也是注意用public(这里用一个假的网络请求代替下)

//假装自己是个网络请求
    public void reqJiade(){
        List<String> list = new ArrayList<>();
        for(int i=0;i<200;i++){
            list.add("扫地欧尼"+i);
        }
        //请求成功后再调用set方法
        liveString.setValue(list);
        txt.set("文本改变");
    }

③Activity调用viewmodel中的请求网络的方法,并设置好对应livedata的监听。下文的Activity中详细说明

完整的ViewModel类代码

public class TestMvvmViewModel extends BaseAppViewModel {

    public MutableLiveData<CityAreasBean> liveAddress = new MutableLiveData<>();
    public MutableLiveData<List<String>> liveString = new MutableLiveData<>();

    //文本内容
    public ObservableField<String> txt = new ObservableField<>();

    //获取地址数据
    public void reqAddress(){
        sendHttp(getRetrofitClient().getcityaddress(), new BaseObserver<CityAreasBean>() {
            @Override
            protected void onSuccess(CityAreasBean o) {
                if(o.isSuccess()){
                    liveAddress.setValue(o);
                }else {
                    ToastUtils.showShort(o.getResultMsg());
                }
            }
        });
    }

    //假装自己是个网络请求
    public void reqJiade(){
        List<String> list = new ArrayList<>();
        for(int i=0;i<200;i++){
            list.add("扫地欧尼"+i);
        }
        //请求成功后调用set方法
        liveString.setValue(list);
        txt.set("文本改变");
    }

    //文本的点击事件
    public void click(View view){
        ToastUtils.showShort("文本被点击");
    }

    public TestMvvmViewModel(@NonNull Application application) {
        super(application);
    }
}

activity类

绑定databinding和viewmodel

①绑定xml对应的databinding和viewmodel,我这里是使用的泛型,根据自己项目中的形式来就行。(databinding是根据xml文件名生成的,例如我的xml是:activity_test,对应的databinding就是ActivityTestBinding)

public class TestMvvmActivity extends AppBaseActivity<ActivityTestBinding, TestMvvmViewModel>

②同步Activity和viewmodel的生命周期,一般都是封装到基类里的,这里根据封装方式调用即可。也是跟着自己项目中的形式来

@Override
    public int initVariableId() {
        return BR.viewModel;
    }

③创建Databinding和viewmodel对象,我这里是用的两个方法。别人项目中多是直接创建对象的方式

//获取databinding和viewmodel的两个方法
    public ActivityTestBinding getBinding(){
        return (ActivityTestBinding) binding;
    }
    public TestMvvmViewModel getVM(){
        return (TestMvvmViewModel)viewModel;
    }

④别的内容就跟mvc,mvp写法一样了。不过mvvm中获取控件对象可以不用findbyid或者eventbus。用databinding对象去调控件id即可(eg:我的TextView的id为:tv_t,我调用这个控件:getBinding().tvT)

⑤这个activity中就写了个Recyclerview列表。以下是完整的Activity代码

完整的Activity代码

public class TestMvvmActivity extends AppBaseActivity<ActivityTestBinding, TestMvvmViewModel> {
    @Override
    public int initContentView(Bundle savedInstanceState) {
        return R.layout.activity_test;
    }

    //数据源,适配器
    private AddressAdapter addressAdapter;
    private List<String> list = new ArrayList<>();

    @Override
    public void initData() {
        super.initData();
        showFullScreen(true);
        //初始化
        first();
        //监听
        monitor();
        //请求网络
//        getVM().reqAddress();
        getVM().reqJiade();
    }

    private void first(){
        getBinding().rl.setLayoutManager(new LinearLayoutManager(this));
        addressAdapter = new AddressAdapter(R.layout.item_txt_center,list);
        getBinding().rl.setAdapter(addressAdapter);
        if(getBinding().rl.getItemDecorationCount() == 0){
            getBinding().rl.addItemDecoration(new MyDecoration());
        }
        //空布局
        View view = View.inflate(this,R.layout.no_layout,null);
        addressAdapter.setEmptyView(view);
    }

    private void monitor(){
        //监听网络请求的结果(接口地址我删了,请求不出来)
        getVM().liveAddress.observe(this,res -> {
//            setRecyclerView(res);
        });
        //假装的网络请求
        getVM().liveString.observe(this,list1 -> {
            setRecyclerView(list1);
        });
    }

    //设置列表
    private void setRecyclerView(List<String> list){
        addressAdapter.setNewData(list);
    }

    //获取databinding和viewmodel的两个方法
    public ActivityTestBinding getBinding(){
        return (ActivityTestBinding) binding;
    }
    public TestMvvmViewModel getVM(){
        return (TestMvvmViewModel)viewModel;
    }

    @Override
    public int initVariableId() {
        return BR.viewModel;
    }

    //recyclerview工具类
    class MyDecoration extends RecyclerView.ItemDecoration{
        @Override
        public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            outRect.set(0,10,0,10);
        }
    }
}

引用文本
链接: 代码demo.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值