Introduced
MVP This architecture has been the focus of discussion in the Android development community, and everyone has their own analytical understanding of the controversy. Until Google officially releases a project built with the MVP structure on GitHub. It feels like it's time to analyze.
Introduction to the MVP architecture
This is not the focus of this article, so excerpt from Li Jiangdong's blog post
Introduction to the MVP architecture
For an application we need to abstract all facets of it, and in the MVP architecture it isolates the UI interface and data, so our application is divided into three levels.
- View: It is also the views layer, which is only responsible for the presentation of the data and provides a friendly interface to interact with the user. Activity or fragment is often used as the view layer in Android development.
- Model: For the model layer is also the data layer. It is different from the model in the MVC architecture, where it is more than just the data models. In the MVP architecture, the model is responsible for accessing data, such as reading and writing the database, requests for data from the network, and so on.
- Presenter: For Presenter layer He is the bridge between the view layer and the model layer and processes the business logic. Model and view cannot interact directly in the MVP architecture. So in the presenter layer it will get the required data from the model layer and do some proper processing to show it to the view layer. This isolates the view from the model by presenter so that there is no coupling between the view and the model, and the business logic is drawn away from view. Better to make unit testing possible.
The relationship between the various components of the MVP is well demonstrated.
It can be seen that the view layer is no longer associated with the model layer, between them through the Presenter Layer Association, where the apparent sense of the P-layer task will be heavier, the logic will be relative to the other layers of complexity, but also the MVP of the most critical layer.
In the MVP architecture, these three layers are abstracted separately into their respective interfaces. The interfaces are used to isolate the layers, and the presenter of the view and model depend on their respective interfaces. This conforms to the principle of interface isolation, and it is interface-oriented programming. A view interface is included in the presenter layer and is dependent on the model interface to associate the model layer with the view layer. For the view layer, a Presenter member variable is held and only the calls to the presenter interface are retained, and the specific business logic is all handled by the presenter interface implementation class.
Interface-oriented Programming: each level is not directly to its upper layer to provide services (that is, not directly instantiated in the upper layer), but by defining a set of interfaces, only the upper layer exposes its interface functionality, the upper layer for the lower layer is only the interface dependency, and not rely on the specific class.
Code Analysis Project Description
This paper mainly analyzes:
Base MVP architecture TODO-MVP and responsive MVP architecture Todo-mvp-rxjava
Google Now publishes 7 items on GitHub:
Each project is a sticky note app that uses the MVP architecture but each project will be a little different. At present, most of the network is the analysis of the first TODO-MVP, as the basis of other projects, comparative analysis Todo-mvp-rxjava find out the difference between the two and the same point, is the main content of this article.
For brevity, the conventions are:
MVP: Refer to TODO-MVP Project
Mvp-rxjava: Referring to Todo-mvp-rxjava project
Responsive MVP: As a Chinese description of Mvp-rxjava
Basic class Analysis
This chapter mainly analyzes the difference between MVP and Mvp-rxjava two Project Foundation classes, analyzes the difference between the same function MVP and the response MVP, and extracts the same points.
Basic Class Baseview
Baseview as the parent of all view layers, the function is to implement the P-layer dependency injection. Both MVP and Mvp-rxjava use the same logic.
The code is as follows:
publicinterface BaseView<T> { void setPresenter(T presenter);}
The concrete implementation of the view layer Xxfragment implementation of the interface, you can get its associated with the P-layer injection.
//内部变量 从setPresenter方法注入 private AddEditTaskContract.Presenter mPresenter;@Override publicvoidsetPresenter(@NonNull AddEditTaskContract.Presenter presenter) { mPresenter = checkNotNull(presenter); }
The timing of the injection is certainly after the P-layer has been instantiated, so we can see in the corresponding P-layer construction method that this code:
public AddEditTaskPresenter(@Nullable@NonNull TasksDataSource tasksRepository, @NonNull AddEditTaskContract.View addTaskView) { mTaskId = taskId; mTasksRepository = checkNotNull(tasksRepository); mAddTaskView = checkNotNull(addTaskView); //向V层注入自己 自己就是对应的P层实例 mAddTaskView.setPresenter(this); }
The above 3 pieces of code, give me feel like this.
Basic Class Basepresenter
Basepresenter, as the parent class of all P-layers, mainly implements the V-layer and P-layer life cycle synchronization.
The response MVP here is obviously different from the MVP,
MVP's P-Layer parent code:
publicinterface BasePresenter { void start();}
In the life cycle onresume of the specific implementation class xxfragment of the view layer, start the P-layer work by injecting the resulting P-layer instances.
@Override publicvoidonResume() { super.onResume(); mPresenter.start(); }
The P-Layer parent of the response MVP:
publicinterface BasePresenter { void subscribe();//开启订阅 void unsubscribe();//结束订阅}
A two-step operation is required in the specific implementation class xxfragment of the view layer to synchronize the life cycle of P-and V-layers
@Override publicvoidonResume() { super.onResume(); mPresenter.subscribe();//V层获得焦点 开始订阅 } @Override publicvoidonPause() { super.onPause(); mPresenter.unsubscribe();//V层失去焦点 取消订阅 }
The reason for this is that the characteristics of Rxjava are determined.
The data model in the response code is a data stream that can be observed, and the data is ready for launch at any time.
What we need to do is to start subscribing to the data and receive the data at the point where the data is needed. Unsubscribe data from data is no longer needed, so data is no longer sent. This is an important operation in the use of Rxjava.
In a general MVC schema project using Rxjava, if you use fragment as the primary presentation class for data, you define the internal variable Compositesubscription object Subscriber collection directly, and operate uniformly in the OnDestroy lifecycle callback. Cancel the subscription you are waiting for, because the current view is not visible.
The code is this:
//Parent class provides a unified management approach Public Abstract class basefragment extends Fragment { PrivateCompositesubscription mcompositesubscription;//The internal of this class is maintained by set<subscription> subscribers //methods provided to subclasses Public void AddSubscription(Subscription s) {if( This. mcompositesubscription = =NULL) { This. mcompositesubscription =NewCompositesubscription (); } This. Mcompositesubscription.add (s); }@Override Public void OnDestroy() {Super. OnDestroy ();//Unified cancellation upon destruction if( This. mcompositesubscription! =NULL) { This. Mcompositesubscription.unsubscribe (); } }}
In the response MVP architecture, the P-layer, as the main implementation of the control logic, needs to synchronize with the V-layer's life cycle, and move the code to the P-layer.
In my other blog post, rxandroid and retrofit use records-specific code and analysis for the network calls and lifecycles.
Contract Contract Class
Unlike other MVP programs, the official MVP framework is defined by the Xxcontract contract class, which unifies the P-layer and V-layer interfaces in the contract class, and provides a clearer view of what functions are in the presenter layer and the view layer to facilitate our later maintenance. This is a class that other MVP architectures do not have. Both MVP and Mvp-rxjava use the same logic.
Each contract class defines the P-layer data manipulation method and the V-Layer control UI method.
And be able to pass parameters to the required values.
The contract classes for each module require that we abstract, define methods and parameters according to the specific requirements.
The code below is to add the contract class for the task module, and the method name gives you an idea of what the V-layer and P-layers need to be implemented logically.
Public interface addedittaskcontract { interface View extends baseview<Presenter> { voidShowemptytaskerror ();voidShowtaskslist ();voidSettitle (String title);voidSetDescription (String description);BooleanIsActive (); } interface Presenter extends basepresenter { voidCreateTask (string title, string description);voidUpdatetask (string title, string description);voidPopulatetask (); }}
Activity Binding Class
The activity class is no longer responsible for any view layer functionality in the official MVP architecture. Both MVP and Mvp-rxjava use the same logic.
- The normal view controls are contained in the fragment of the V-layer.
- Even controls in the layout file and fragment siblings
FloatingActionButton
are controlled by fragment
- The menu view of the same layout file and fragment siblings is also controlled by fragment.
This makes fragment a real view layer. The SRP that makes the activity conform to the principle of object-oriented design (single Responsibility Principle).
The most important function of activity is the binding of P layer to m/v layer.
// Create the presenter //P层的构造 依赖注入 new TaskDetailPresenter( taskId,//P层需要的关键数据 任务id Injection.provideTasksRepository(getApplicationContext()),//Model层的注入 taskDetailFragment//View层 );
See the above code, feel very fit
View Layer
Said so much finally to the MVP view layer, the official MVP architecture fragment as the view layer implementation class.
After layering, the fragment code is much simpler.
Implements implements the related interface method, does the view operation, distributes to the P layer to do the processing. Get the P-layer callback display data.
The following code, as an example, implements Peer view control.
As mentioned above: even controls in the layout file and fragment siblings are FloatingActionButton
controlled by fragment
//得到和自己同级的View // Set up floating action button FloatingActionButton fab = (FloatingActionButton) getActivity().findViewById(R.id.fab_edit_task); //响应点击事件 分发给P层 fab.setOnClickListener(new View.OnClickListener() { @Override publicvoidonClick(View v) { mPresenter.editTask(); } });
The same menu also overrides onCreateOptionsMenu()
methods and onOptionsItemSelected()
methods to control the view of menus.
Presenter Layer
The Xxpresenter class in each package is a specific P-layer control class. Because the model data layer is responsible for reading the data, the P-layer code logic is simple.
The data is obtained from the M layer and the logical judgment is distributed to the V-layer. Or to send a read and write operation to the M layer, the callback operation is the result of success.
and its data source model layer, is just the activity class inside the dependency injected in.
//数据层 通过构造方法得到的依赖注入privatefinal TasksRepository mTasksRepository;
It is worth mentioning that the response MVP and MVP will have different access to the data.
MVP's P-layer acquires data logic
There are two issues to note in the interaction between P-and M-layers.
- The data-tier read-write operation occurs on the child thread, and the P-layer eventually needs to send the data to the V layer for the UI main thread operation. Therefore, a specific data-sending class in the model layer is thread-handling. The P-layer callback will correctly distribute the data to the V-layer display.
Now that you are using multi-threading, if you are using handler-to-thread communication, if an operation on the sub-thread takes a long time to return the data, and if the fragment of the V-layer has exited calling the OnDestroy method, then if the P-layer holds a reference to V-layer to send the data to him, It is possible to cause a memory leak.
In short, the MVP project architecture, the time-consuming task is not handled well, there is the possibility of abnormal or memory leaks.
The P-layer in MVP gets the data by the interface callback, the following code:
mtasksrepository.gettask (Mtaskid, new Tasksdatasource.gettaskcallback () { @Override public void ontaskloaded (Task Task) {//the view is not being able to handle UI updates anymore if (!mtaskdetailview.isactive ()) {return ; } mtaskdetailview.setloadingindicator (false ); if (null = = Task) {Mtaskdetailview.showmissingtask (); } else {showtask (Task); } }
The P-Layer data acquisition logic of the response MVP
The above two problems can be solved very well in the response MVP.
If you have used Rxjava, the following code, I believe there is no need to say anything. You can skip the instructions below.
Mtaskdetailview.setloadingindicator (true); Subscription Subscription = mtasksrepository. Gettask (Mtaskid)//Remove observable data observable<task>. Subscribeon (Schedulers.io ())//Generate data on IO thread. Observeon (Androidschedulers.mainthread ())//Distributing data on the UI thread. Subscribe (NewObserver<task> () {@Override Public void oncompleted() {Mtaskdetailview.setloadingindicator (false); }@Override Public void OnError(Throwable e) { }@Override Public void OnNext(Task Task) {ShowTask (Task); } }); Msubscriptions.add (subscription);//Join a collection to unsubscribe in a timely manner
Code Description:
Subscribeon (): Specifies the thread that occurs subscribe (), which is the thread where observable.onsubscribe is activated. Or an event-generated thread.
Observeon (): Specifies the thread that the Subscriber is running on. Or a thread called event consumption.
So the M layer sends over the data, as long as the P layer two lines of code to fix the thread switch, and then directly subscribe to wait for the data to arrive. At the same time to join the Subscriber management set in the corresponding life cycle of the unified cancellation.
Model Layer
The model layer is almost finished when I feel that I have said so much.
The data layer is responsible for reading and writing data locally or remotely, and each application will have a different data structure representation and storage format.
The official MVP data is stored using SQL database, and the external maintenance of a lazy singleton to TasksRepository
do data caching.
The MVP architecture distributes data through interface callbacks, and the response MVP obtains observable data through observable.
If you combine the retrofit network framework, which response MVP model layer data source. Is that it can be servicegenerator.
Retrofit static Construction method constructs the network Request object, the incoming interface, the proxy pattern generates the data, the P layer can directly obtain the data.
Of course this is just my initial idea, intended to be used in my personal project.
Graphic
Through the above analysis of the MVP function of each module, the final last picture, Android official MVP of the entire project logic diagram.
Need specific code to go to GitHub on clone
Summarize
- The structure logic of the official MVP is clearly defined by comparative analysis.
- Each class conforms to the principle of object-oriented design and adopts the principle of single responsibility. Clear division of work across the project structure.
- The level is limited, please correct us. Dependency Injection This piece I do not know very well, the specific needs of everyone to Google.
- Finally, the author puts forward some ideas about the response-type MVP combination retrofit.
Reference
- Android Official MVP Architecture interpretation
- interface-oriented Programming (I.)--Ideological foundation
- RxJava for Android Developers
MVP Architecture-android Official MVP program and responsive Mvp-rxjava Project architecture analysis and Comparative interpretation