Since the official MVP Sample came out, the MVP has been in a hot state, and even the small code has not been able to avoid joining the MVP pit. The ARCHITECTURE of MVP, which has been in the pit for nearly 2 years, finally has to say “byes”. Recently, due to the relatively stable project of the company, a large reconstruction has been made, and the original MVP architecture has been switched to T-MVVM. The whole project is much cleaner. # # #

MVP disadvantages: In addition to the logic, there is a large number of View->Model, Model->View logic operation, cause Presenter oversize, difficult maintenance. * Rendering of the UI is in Presenter, so UI and Presenter interact too often. Presenter renders too much of the UI and often interacts too much with a particular UI. When the UI changes, presenters also need to change * The number of interfaces has exploded, so to speak, the amount of code has multiplied, and the interaction needs to pass information through the interface has become unbearable.Copy the code

Basically used MVP code friends can find many of the above disadvantages. So the small code tried to transition from traditional MVP to T-MVVM, deep structure, no cumbersome transfer of information. If the business is not very large or relatively simple, there is no need to use THE MVP and the project becomes more complex.

T-mvvm code, if help remember star oh github.com/SelfZhangTQ… Based on the ViewModel, LiveData, Retrofit, Rxjava realize T – MVVM architecture, the architecture of the generic qualifier, depth of decoupling.

ViewModel advantages: * Synchronous association life cycle, * data sharing, * strong reuse, LiveData advantages: * Ensure that the UI data state, * no memory leaks, will not Crash because the Activity is not visible, * no more artificial processing life cycle, * shared resources,Copy the code

This architecture does not use DataBinding for the following reasons:

* Data binding increases the difficulty of Bug debugging, * complex pages, model will be very large, although easy to use is also easy to ensure the consistency of the data, when the long-term holding, is not conducive to the release of memory, * two-way data binding is not conducive to View reuse,Copy the code

T-mvvm architecture layering code 1: Start by defining the BaseViewModel base class

/ * * * @ the author: tqzhang on 18/7/26 16:15 */ public class BaseViewModel<T extends BaseRepository> extends AndroidViewModel { public T mRepository; public BaseViewModel(@NonNull Application application) { super(application); mRepository = TUtil.getNewInstance(this, 0); } @Override protected void onCleared() { super.onCleared(); if (mRepository ! = null) { mRepository.unSubscribe(); }}}Copy the code

BaseViewModel initializes the Repository data store with the generic BaseRepository subclass and calls the onCleared when the Activity/Fragment executes the onDestroy() lifecycle method. Page destruction is used to cancel operations such as network requests or resource releases.

Fetching web data directly from the ViewModel is not recommended for normal development, so we’ll hand over the job to a new module, Repository. Repository only handles data processing and provides a clean API for switching data sources.

2: Redefine BaseRepository

public abstract class BaseRepository {

     protected ApiService apiService;

     public BaseRepository() {
             if (null == apiService) {
                 apiService = HttpHelper.getInstance().create(ApiService.class);
             }
     }

     private CompositeSubscription mCompositeSubscription;

     protected void addSubscribe(Subscription subscription) {
            if (mCompositeSubscription == null) {
                mCompositeSubscription = new CompositeSubscription();
            }
           mCompositeSubscription.add(subscription);
      }

     public void unSubscribe() {
             if (mCompositeSubscription != null && mCompositeSubscription.hasSubscriptions()) {
            mCompositeSubscription.clear();
    }
}
Copy the code

BaseRepository is relatively simple. It mainly acquires ApiService and network request subscription container to facilitate the management of network requests.

3: Then customize the AbsLifecycleFragment base class to inherit BaseFragment, BaseFragment can be written by yourself. If t-MVVM is not required, BaseFragment can be inherited without affecting each other.

public abstract class AbsLifecycleFragment<T extends BaseViewModel> extends BaseFragment { protected T mViewModel; /** * init view * @param state */ @Override public void initView(Bundle state) { mViewModel = VMProviders(this, TUtil.getInstance(this, 0)); if (null ! = mViewModel) { dataObserver(); } } /** * create ViewModelProviders * * @return ViewModel */ protected <T extends ViewModel> T VMProviders(BaseFragment fragment, @NonNull Class<T> modelClass) { return ViewModelProviders.of(fragment).get(modelClass); /** * Get network data */ protected void getRemoteData() {}}Copy the code

Get the Class from the BaseViewModel subclass generic type parameter in the initView method, After instantiating ViewModel via viewModelproviders.of (fragment).get(modelClass)), our base class is basically written.

4: Let’s get the list of articles in a simple business practice.

4-1:ArticleFragment

/ * * * @ the author: zhangtianqiu on 18/7/2 14:40 */ public class ArticleFragment extends AbsLifecycleFragment<ArticleViewModel> { protected TRecyclerView mRecyclerView; protected StaggeredGridLayoutManager layoutManager; protected MultiTypeAdapter adapter; public static ArticleFragment newInstance() { return new ArticleFragment(); } @Override public int getLayoutResId() { return R.layout.fragment_list; } @Override public void initView(Bundle state) { super.initView(state); layoutManager=new new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL); GetRemoteData (); } public void initAdapter(){adapter= new MultiTypeAdapter.builder <>().bindarray (ArticleInfoVo. new ArticleRem1ItemHolder(context) , new ArticleRem2ItemHolder(context) , new ArticleRem3ItemHolder(context)) .bind(HeaderVo.class, new HeaderViewHolder(context, rogressStyle.Pacman)) .bind(FootVo.class, new FootViewHolder(context, ProgressStyle.Pacman)) .build(); / / data observed @ Override protected void dataObserver () {mViewModel. GetArticleList (). Observe (this, articleVo - > {the if (null! = articleVo) { mRecyclerView.refreshComplete(articleVo.data.list, false); }}); } / / access network data @ Override protected void getRemoteData () {mViewModel. GetArticleList (typeId, lastId); }}Copy the code

We can see that ArticleFragment only UI initialization, send network request action and data observation update UI, list display using TRecyclerView, welcome star for holder development of high reuse, multi-type refresh library, from now on only care about your list Item display. See you Mass Implementation of interfaces removes a lot of code that passes information through interfaces in MVP via generics.

4-1:ArticleViewModel

/ * * * @ the author: tqzhang on 18/7/26 16:15 */ public class ArticleViewModel extends BaseViewModel<ArticleRepository> { private MutableLiveData<ArticleVo> mArticleData; public ArticleViewModel(@NonNull Application application) { super(application); } public LiveData<ArticleVo> getArticleList() { if (mArticleData == null) { mArticleData = new MutableLiveData<>(); } return mArticleData; } public void getArticleList(String lectureLevel1, String lastId) { mRepository.loadArticleRemList(new CallBack<ArticleVo>() { @Override public void onNext(ArticleVo articleObject) { mArticleData.postValue(articleObject); } @Override public void onError(String e) { } } }); }Copy the code

The ArticleViewModel holds the data observation container LiveData and actually initiates the network request action, after receiving the data returned by the server through MarticleData.postValue (articleObject); Notify the Observer of data changes. Note that setValue can only be called in the main thread, postValue can be called in any thread, and postValue must be called to update the value of LiveData in a background child thread.

4-3:ArticleRepository

/ * * * @ the author: tqzhang on 18/7/28 13:00 */ public class ArticleRepository extends BaseRepository { public void loadArticleRemList(final  CallBack<ArticleVo> listener) { addSubscribe(apiService.getArticleRemList() .compose(RxSchedulers.io_main()) .subscribe(new RxSubscriber<ArticleVo>() { @Override public void onSuccess(ArticleVo articleObject) { listener.onNext(articleObject); } @Override public void onFailure(String msg) { listener.onError(msg); }})); }Copy the code

Finally, data is provided in ArticleRepository, which only provides data at the network layer. In practical applications, loacl data and remote data can be disdivided and processed according to project requirements. So far we a simple business code is completed, is a donkey is a horse, pull out of the walk to know, real knowledge from practice, the effect diagram is provided:

Github Address: github.com/SelfZhangTQ… Welcome to talk, Star.