Jetpack mvvm 终

  • 前面3篇讲完了mvvm必要的3个库ViewModel LiveData DataBinding
  • 本篇将讲解如果用这3者结合组成mvvm的架构
  • 在此之前让我们先了解下mvc mvp 最后再来说下mvvm
MVC
image.png
  • 其实Android本身就有mvc的例子了
  • 比如直接新建一个Activity 在xml布局定义一个按钮实现点击事件 当用户点击按钮的时候我们在按钮的OnClickListener接口回掉中做一个1+1的运算Toast弹出1+1的结果 这一个简单的步骤就包含了mvc的结构了
  • M指Model(模型层)在上述的例子指1+1的运算结果
  • V指View是视图 用户看到的页面
  • C指Controller控制器在上述例子对应点击时间
  • 当View视图被用户点击,然后Controller监听到了这个操作进行Mode操作得到2的值反馈给View,然后用户看到了View所弹出Toast消息
  • 这个例子很好的对应了上图Model、View、Controller的关系
    优点:
    1、业务逻辑全部分离到Controller中,模块化程度高。
    2、观察者模式可以做到多视图同时更新。
    缺点:
    1、Model和View之间是直接进行交互,就必然会导致Model和View之间的耦合。
    2、所有逻辑都写在Controller层,导致Controller层特别臃肿。
  • 优缺点这个百度一大堆我就直接抄了
  • 适用场景:适用于功能较少、业务逻辑简单、界面不复杂的小型项目。
MVP
  • mvp这个呢很多大型的商业app啥的大都用的这个结构,可以说在android算是主流的架构模式
  • M 还是那个Model
  • V 还是那个视图View
  • P 就是Presenter(主持人) 在下面的关系图中P持有M和V做M、V之间的交互桥梁
image.png
  • 对比mvc可以发现由于Presenter的存在直接处理了V、M直接的耦合,所以比mvc 降低了耦合。
  • 具体实现就不扯了网上可以搜罗一大堆
  • 下面放个我之前写的Demomvp-retrofit2-rxjava2

优点:
1、模型与视图完全分离,我们可以修改视图而不影响模型。
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter内部。
3、我们可以将一个Presenter用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)。
缺点:Presenter作为桥梁协调View和Model,就会导致Presenter变得很臃肿,维护比较困难。

  • 哈哈哈,这个优缺点我也是抄的
MVVM
  • 这才是本文肉戏


    image.png
  • M不在是前面的Model了,MVVM的Model主要是封装数据存储或操作的一些逻辑(工具类),还会提供一系列的实体类用于UI绑定。

  • V View指做处理界面数据的展示,不做数据处理、业务逻辑等操作。

  • VM ViewModel做数据的获取业务逻辑操作然后通过数据绑定(DatabBinding)和xml进行绑定

优点:
  • 低耦合,数据和业务逻辑处于一个独立的ViewModel中,ViewModel只需要关注数据和业务逻辑,不需要和View层打交道。
  • 可重用性,你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
  • 可分开独立开发,MVVM的分工是非常明显的,由于View和ViewModel之间是松散耦合的:一个是处理业务和数据、一个是专门的UI处理。所以,完全可以由两个人分工来做,一个做UI(XML和Activity)一个写ViewModel,效率更高。
  • 由于各层分工明确,极便于单元测试;
  • 相对于MVP而言,MVVM不需要我们手动的处理大量的View和Model相关操作,也非常完美的解耦了View层和ViewModel。
缺点:
  • 数据绑定使得 Bug 很难被调试,你看到界面异常了,有可能是你 View 的代码有 Bug,也可能是 Model 的代码有问题。数据绑定使得一个位置的 Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。

  • 对于过大的项目,数据绑定需要花费更多的内存,而对与过于简单的界面,使用MVVM无异是杀鸡用牛刀。


  • 正式开始敲代码

  • 网络的部分我用的retrofit2+Rxjava组合,用了wanandroid的公开的接口。

public class MvvMViewmodel extends ViewModel {
    public MutableLiveData mutableLiveData = new MutableLiveData<>();
    public MutableLiveData state = new MutableLiveData<>();
    public LiveData> listLiveData;
    private  int page =0;
    public  List list = new ArrayList<>();
    public CompositeDisposable dis;


    public MvvMViewmodel() {
        dis = new CompositeDisposable();
        listLiveData = Transformations.switchMap(mutableLiveData, new Function>>() {
            @Override
            public LiveData> apply(Integer input) {
                return getData(input);
            }
        });

    }
    public void getPageUpData(){
       mutableLiveData.setValue(page>0?page-1:page);
    }
    public void getPageNextData(){
        mutableLiveData.setValue(page+1);
    }

    private LiveData> getData(int page){
        MediatorLiveData> mediatorLiveData = new MediatorLiveData<>();
        HttpData.getRetrofit().create(PathApiService.class).getNes(page)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        state.setValue(new State(StateType.LOADING,""));
                        dis.add(d);
                    }

                    @Override
                    public void onNext(WanAndroidNewsBean wanAndroidNewsBean) {
                        state.setValue(new State(StateType.SUCCESS,""));
                        mediatorLiveData.setValue(wanAndroidNewsBean.getData().getDatas());
                    }

                    @Override
                    public void onError(Throwable e) {
                        state.setValue(new State(StateType.ERROR,e.getMessage()));
                    }

                    @Override
                    public void onComplete() {
                        Log.e("TAGSS","onComplete");
                    }
                });
        return mediatorLiveData;
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        if(dis!=null){
            dis.dispose();
        }
    }
}
public class MvvmMainActivity extends BaseActivity {
    private MvvMViewmodel viewmodel;
    private ActivityMvvmMainBinding activityMvvmMainBinding;
    private RecycleAdapter recycleAdapter;
    private Dialog diglog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public void init() {
        diglog = MyDiglog.createLoadingDialog(this,"请求中");
        activityMvvmMainBinding= getViewDataBinding();
        viewmodel = new ViewModelProvider(this).get(MvvMViewmodel.class);
        diglog.show();
        activityMvvmMainBinding.setLifecycleOwner(this);
        viewmodel.getPageUpData();
        activityMvvmMainBinding.setViewModel(viewmodel);
        activityMvvmMainBinding.recycle.setLayoutManager(new LinearLayoutManager(this));
        recycleAdapter = new RecycleAdapter(viewmodel.list);

        activityMvvmMainBinding.recycle.setAdapter(recycleAdapter);
        viewmodel.listLiveData.observe(this, new Observer>() {
            @Override
            public void onChanged(List itemDetailsBeans) {
             viewmodel.list.clear();
             viewmodel.list.addAll(itemDetailsBeans);
             recycleAdapter.notifyDataSetChanged();
            }
        });

        viewmodel.state.observe(this, new Observer() {
            @Override
            public void onChanged(State state) {
                diglog.dismiss();
                switch (state.getCode()){
                    case ERROR:
                        Toast.makeText(MvvmMainActivity.this,state.getMsg(),Toast.LENGTH_LONG).show();
                        break;
                    case LOADING:
                        diglog.show();
                        break;

                }
            }
        });
    }

    @Override
    public int getLayout() {
        return R.layout.activity_mvvm_main;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(diglog!=null){
            diglog.dismiss();
        }
        diglog= null;
    }

}


    
        

    


    
    
效果图
  • 从代码上可以把我的MvvMViewmodel类中的变量mutableLiveData
    、listLiveData、list看作是Moldel部分,通过ViewModel部分用LiveData跟DataBinding对View部分(activity和xml)进行了绑定,当用户点击下一页就回去执行getPageNextData方法,当listLiveData获取到数据就去更新适配器的数据。
  • 大概就这么多了
  • 代码都在jetpackDemo欢迎Star
  • 可以说的是认真看完这个系列的文章,在自己根据文章的源码解读部分看下源码,相信你在看网上的MVVM列子什么的就不会让你一看懵逼二看还是懵逼了


你可能感兴趣的:(Jetpack mvvm 终)