• The previous three articles covered the three libraries necessary for MVVM, ViewModel LiveData DataBinding
  • This article will explain how to combine these three elements to form an ARCHITECTURE for MVVM
  • Before that, let’s take a look at the MVC MVP and finally talk about MVVM
MVC

  • Android already has MVC examples
  • For example, just create a new Activity and define a button in the XML layout to implement the click event. When the user clicks the button, we perform a 1+1 operation in the OnClickListener interface callback of the button. Toast brings up the result of 1+1
  • M is for Model. In the example above, M is the result of the 1+1 operation
  • V for View is the page that the View user sees
  • C refers to Controller. Click time corresponding to the Controller in the preceding example
  • When the View View is clicked by the user, the Controller listens to the operation and performs Mode operation to get the value of 2 and feedback to the View. Then the user sees the Toast message displayed by the View
  • This example perfectly corresponds to the relationship between Model, View and Controller in the figure above

Advantages: 1. All the business logic is separated into Controller, which is highly modularized. 2. Observer mode can update multiple views simultaneously. Disadvantages: 1. Direct interaction between Model and View will inevitably lead to coupling between Model and View. 2, all logic is written in the Controller layer, resulting in the Controller layer is very bloated.

  • Advantages and disadvantages of this Baidu a lot of I directly copied 😂
  • Application scenario: Suitable for small projects with few functions, simple service logic, and uncomplicated interfaces.
MVP
  • Most of the large commercial apps use this structure, which can be said to be the mainstream architecture mode in Android
  • M is the same Model
  • V is still the same View View
  • In the diagram below, P holds M and V as an interaction bridge between M and V

  • Compared with MVC, it can be found that Presenter directly deals with the direct coupling of V and M, so it reduces the coupling compared with MVC.
  • I don’t know how to implement it. There’s a whole bunch of stuff on the Internet
  • So here’s demomvp-RetroFIT2-rxJavA2 that I wrote earlier

Advantages: 1. The model is completely separated from the view, and we can modify the view without affecting the model. Models can be used more efficiently because all interaction takes place in one place — inside the Presenter. 3. We can use a Presenter for multiple views without changing the Presenter logic. This feature is useful because the view changes more frequently than the model. 4. If we put the logic in Presenter, we can test it out of the user interface (unit testing). Cons: Presenters act as a bridge between a View and a Model, which can cause them to become bloated and difficult to maintain.

  • Ha ha ha, I also copied this advantage and disadvantage
MVVM
  • That’s the meat of the story

  • M is no longer the previous Model. MVVM models mainly encapsulate some logic for data storage or operations (utility classes), and also provide a series of entity classes for UI binding.
  • V View refers to the display of interface data without data processing and business logic operations.
  • The VM ViewModel does the business logic of retrieving the data and then binds it to XML via DatabBinding
Advantages:
  • Low coupling, data and business logic in a separate ViewModel, the ViewModel only needs to focus on the data and business logic, does not need to deal with the View layer.
  • Reusability, you can put some view logic in a ViewModel and have many views reuse that view logic.
  • Developed separately, the division of labor between MVVM is very obvious because the View and ViewModel are loosely coupled: one handles business and data, the other specialized UI processing. Therefore, it is perfectly possible for two people to do the task, one to do the UI (XML and Activity) and the other to write the ViewModel, which is more efficient.
  • As the division of labor of each layer is clear, it is very convenient for unit testing;
  • In contrast to MVP, MVVM does not require us to handle a lot of View and Model operations manually, and perfectly decouples the View layer from the ViewModel.
Disadvantages:
  • Data binding makes it hard to debug bugs, so if you see an interface exception, it could be your View code that has a Bug, it could be your Model code that has a Bug. Data binding allows bugs in one location to be quickly transferred to another location, making it difficult to locate the original problem.
  • Data binding costs more memory for large projects, and MVVM is a dead end for interfaces that are too simple.

  • Start typing code
  • For the web part I used retrofit2+Rxjava, using wanAndroid’s public interface.
public class MvvMViewmodel extends ViewModel { public MutableLiveData<Integer> mutableLiveData = new MutableLiveData<>(); public MutableLiveData<State> state = new MutableLiveData<>(); public LiveData<List<WanAndroidNewsBean.ItemDetailsBean>> listLiveData; private int page =0; public List<WanAndroidNewsBean.ItemDetailsBean> list = new ArrayList<>(); public CompositeDisposable dis; public MvvMViewmodel() { dis = new CompositeDisposable(); listLiveData = Transformations.switchMap(mutableLiveData, new Function<Integer, LiveData<List<WanAndroidNewsBean.ItemDetailsBean>>>() { @Override public LiveData<List<WanAndroidNewsBean.ItemDetailsBean>> 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<List<WanAndroidNewsBean.ItemDetailsBean>> getData(int page){ MediatorLiveData<List<WanAndroidNewsBean.ItemDetailsBean>> mediatorLiveData = new MediatorLiveData<>(); HttpData.getRetrofit().create(PathApiService.class).getNes(page) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<WanAndroidNewsBean>() { @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(); }}}Copy the code
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, "request"); 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<List<WanAndroidNewsBean.ItemDetailsBean>>() { @Override public void onChanged(List<WanAndroidNewsBean.ItemDetailsBean> itemDetailsBeans) { viewmodel.list.clear(); viewmodel.list.addAll(itemDetailsBeans); recycleAdapter.notifyDataSetChanged(); }}); viewmodel.state.observe(this, new Observer<State>() { @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; }}Copy the code
<? The XML version = "1.0" encoding = "utf-8"? > <layout> <data> <variable name="viewModel" type="com.sanyue.jetpakcdemonew.mvvm.MvvMViewmodel" /> </data> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".mvvm.MvvmMainActivity"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycle" android:layout_width="match_parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@+id/page_up" Android :layout_height="0dp"/> <Button android:id="@+id/ page_UP "Android :layout_width="wrap_content" android:onClick="@{()->viewModel.getPageUpData()}" android:enabled="@{viewModel.mutableLiveData>0?true:false}" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/pageIndex" app:layout_constraintBottom_toBottomOf="parent" android:layout_height="wrap_content"/> <TextView android:id="@+id/pageIndex" android:layout_width="wrap_content" android:textColor="@android:color/holo_red_dark" android:textSize="18sp" app:layout_constraintLeft_toRightOf="@+id/page_up" app:layout_constraintRight_toLeftOf="@+id/page_down" app:layout_constraintTop_toTopOf="@+id/page_down" app:layout_constraintBottom_toBottomOf="@+id/page_down" android:text="@{String.valueOf(viewModel.mutableLiveData)}" android:layout_height="50dp"/> <Button android:id="@+id/page_down" android:layout_width="wrap_content" Android: text = "next page" the android: onClick = "@ {() - > viewModel. GetPageNextData ()}" app:layout_constraintLeft_toRightOf="@id/pageIndex" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:layout_height="wrap_content"/> </androidx.constraintlayout.widget.ConstraintLayout> </layout>Copy the code

  • From the code can be my MvvMViewmodel class variable mutableLiveData

, listLiveData, and List are considered Moldel parts. The ViewModel part uses LiveData to bind the View part (activity and XML) with DataBinding. When the user clicks on the next page, it goes back to the getPageNextData method, and when listLiveData gets the data, it updates the adapter data.

  • That’s about it
  • The code is all in jetpackDemo to welcome Star
  • Can be said to be seriously look at this series of articles, in accordance with the source code interpretation part of the article to see the source code, I believe that you are looking at the MVVM on the Internet what will not let you see meng forced two look or meng forced