Google official MVP mode example project analysis todo-mvp, mvptodo-mvp

Source: Internet
Author: User

Google official MVP mode example project analysis todo-mvp, mvptodo-mvp

Reprinted please indicate the source: http://www.cnblogs.com/cnwutianhao/p/6700668.html

 

Introduction: before Google provides an authoritative architecture implementation, many App projects have more or less architecture problems. The first common problem is that there is no architecture. a page in the requirement corresponds to an activity or fragment in the project, and all the interface response code, business logic code, and Data Request Code are concentrated in it. The second common problem is the constant change in architecture implementation, constantly swinging between various architectures, and failing to find a suitable architecture.

Google official example Project address https://github.com/googlesamples/android-architecture/tree/todo-mvp/

Google provides this example project for two purposes:

  • Provide a basic Model-View-Presenter (MVP) architecture without using any invalid tural frameworks.
  • Act as a reference point for comparing and contrasting the other samples in this project.

Explanation:

  • It provides a basic MVP architecture, rather than other architectures.
  • Use this project to compare it with other similar references.

 

Of course, Google also makes it clear that these examples are only for reference, not for reference.

 

Next we will analyze the implementation of todo-mvp (mvp infrastructure example) from the source code perspective. First, let's start with the overall organization of the project, and then look at the components used by the project. Finally, it is of course the most important implementation method of the specific mvp.

Let's take a look at the project code organization method:

The project contains an app src directory and four test directories: androidTest (UI Layer test), androidTestMock (UI Layer test mock data support), and test (business layer unit test) and mock (support for unit test mock data at the business layer ).

The code of the src directory is fully organized by function. The function is divided into four class files: xActivity, xContract, xFragment, and xPresenter (x represents the business name ).

 

Component usage

Because the project is compiled based on gradle, we can see the entire project dependency from the build. gradle file.

dependencies {    // App's dependencies, including test    compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"    compile "com.android.support:cardview-v7:$rootProject.supportLibraryVersion"    compile "com.android.support:design:$rootProject.supportLibraryVersion"    compile "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion"    compile "com.android.support:support-v4:$rootProject.supportLibraryVersion"    compile "com.android.support.test.espresso:espresso-idling-resource:$rootProject.espressoVersion"    compile "com.google.guava:guava:$rootProject.guavaVersion"    // Dependencies for local unit tests    testCompile "junit:junit:$rootProject.ext.junitVersion"    testCompile "org.mockito:mockito-all:$rootProject.ext.mockitoVersion"    testCompile "org.hamcrest:hamcrest-all:$rootProject.ext.hamcrestVersion"    // Android Testing Support Library's runner and rules    androidTestCompile "com.android.support.test:runner:$rootProject.ext.runnerVersion"    androidTestCompile "com.android.support.test:rules:$rootProject.ext.runnerVersion"    // Dependencies for Android unit tests    androidTestCompile "junit:junit:$rootProject.ext.junitVersion"    androidTestCompile "org.mockito:mockito-core:$rootProject.ext.mockitoVersion"    androidTestCompile 'com.google.dexmaker:dexmaker:1.2'    androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'    // Espresso UI Testing    androidTestCompile "com.android.support.test.espresso:espresso-core:$rootProject.espressoVersion"    androidTestCompile "com.android.support.test.espresso:espresso-contrib:$rootProject.espressoVersion"    androidTestCompile "com.android.support.test.espresso:espresso-intents:$rootProject.espressoVersion"    // Resolve conflicts between main and test APK:    androidTestCompile "com.android.support:support-annotations:$rootProject.supportLibraryVersion"    androidTestCompile "com.android.support:support-v4:$rootProject.supportLibraryVersion"    androidTestCompile "com.android.support:recyclerview-v7:$rootProject.supportLibraryVersion"    androidTestCompile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"    androidTestCompile "com.android.support:design:$rootProject.supportLibraryVersion"}

The Guava library is used in the project, official site address https://github.com/google/guava

This library is a library referenced by Google in java-based projects. The library contains about 14 K methods, which is a large library, it includes collection, cache, concurrency, basic annotation, string processing, io processing, and so on. The use of the Guava library in the project is mainly used to handle the unsafe situation of null, because when we use an object that may be null, we generally add a judgment. For example:

public boolean isEmpty() {        return Strings.isNullOrEmpty(mTitle) &&               Strings.isNullOrEmpty(mDescription);    }

In this way, you do not need to write a lot of code when it is empty. It is indeed much more convenient. However, we do not recommend that you directly introduce such a large library for the sake of null security, because we all know the limit on the number of 65k methods of android apk. If you want to use it, you can use the components involved in the source code directly. Of course, there are many important functions in Guava. Readers can study other functions on their own. For Guava, we will go here first.

 

Test related components

The sample project is very good in terms of testability, because the view logic (view layer) and the business logic (presenter layer) are split, therefore, we can test the UI and Business Code separately. Espresso was introduced for UI testing, junit was introduced for unit testing on the business layer, mockito was introduced for generating testing mock objects, and dexmaker was introduced to support mockito, the introduction of hamcrest makes the matching of the test code closer to the natural language, with higher readability and flexibility.

 

Highlights: Project MVP implementation

1. Base Class

Two Base interfaces, BasePresenter and BaseView, are the Base classes of presenter and view respectively.

public interface BasePresenter {    void start();}

BasePresenter contains the method start (). The function of this method is that presenter starts to obtain data and calls the method in view to change the interface display. The call time is in the onResume method of the Fragment class.

Where start () is called in the project:

 

public interface BaseView<T> {    void setPresenter(T presenter);}

The BaseView includes the setPresenter () method. This method is used to pass the presenter instance to the view. The call time is the constructor of the presenter implementation class.

The place where setPresenter () is called in the project:

 

2. Contract

Unlike all mvp implementations we have seen earlier, Google officially added the contract class to manage all the interfaces of view and presenter in a unified manner. What functions does this method enable view and presenter, easy to understand and easy to maintain. The instance is as follows:

public interface TasksContract {    interface View extends BaseView<Presenter> {        void setLoadingIndicator(boolean active);        void showTasks(List<Task> tasks);        void showAddTask();        ...    }    interface Presenter extends BasePresenter {        void result(int requestCode, int resultCode);        void loadTasks(boolean forceUpdate);        void addNewTask();        ...    }}

 

3. Role of Activity in MVP

Activity is a global controller in the project. It is responsible for creating view and presenter instances and connecting them. The following Code creates view and presenter in the Activity:

TasksFragment tasksFragment =                (TasksFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame);        if (tasksFragment == null) {            // Create the fragment            tasksFragment = TasksFragment.newInstance();            ActivityUtils.addFragmentToActivity(                    getSupportFragmentManager(), tasksFragment, R.id.contentFrame);        }        // Create the presenter        mTasksPresenter = new TasksPresenter(                Injection.provideTasksRepository(getApplicationContext()), tasksFragment);

We can see the entire creation process from above, and note that the created Fragment instance is passed in as the presenter constructor parameter, so that you can call the methods in the view in the presenter.

 

4. MVP implementation and organization

In the instance, Fragment is used as the implementation class of the view layer. Why is it Fragment?

There are two reasons:

Let's take a look at the implementation of the view. Let's take a look at some important methods.

public class TasksFragment extends Fragment implements TasksContract.View {        ...        @Override    public void onResume() {        super.onResume();        mPresenter.start();    }    @Override    public void setPresenter(@NonNull TasksContract.Presenter presenter) {        mPresenter = checkNotNull(presenter);    }        ...    }

The above shows the setPresenter () method, which inherits from the parent class. Through this method, view obtains the presenter instance, so that you can call the presenter code to process the business logic. We can see that the start () method of presenter is also called in onResume.

Next let's look at the implementation of presenter.

public class TasksPresenter implements TasksContract.Presenter {    ...    public TasksPresenter(@NonNull TasksRepository tasksRepository, @NonNull TasksContract.View tasksView) {        mTasksRepository = checkNotNull(tasksRepository, "tasksRepository cannot be null");        mTasksView = checkNotNull(tasksView, "tasksView cannot be null!");        mTasksView.setPresenter(this);    }    @Override    public void start() {        loadTasks(false);    }        ...}

The presenter constructor calls the setPresenter () method of view to pass in its own instance. The start () method processes data loading and display. If you need to make corresponding changes to the interface, you can directly call the view layer method, so that the view layer and the presenter layer can be well divided.

 

Finally, the model layer is implemented. The biggest feature of the model layer in the project is that it is assigned the responsibility of Data Acquisition. It is different from the normal model layer that only defines object objects. In the instance, data acquisition, storage, and data status changes are all tasks at the model layer. presenter calls the data processing logic at the layer as needed and transmits the callback when needed. In this way, model, presenter, and view only process their respective tasks. This implementation is indeed the best interpretation of a single responsibility.

 

5. Conclusion:

Let's take a look at the features of the official implementation method. The first is complexity. From the analysis above, we can see that the overall complexity is still relatively low and easy to learn. Then it is testability, because the UI code and Business Code are split, the overall testability is very good. The UI Layer and the business layer can perform unit tests separately. Finally, the maintainability and scalability are achieved. Due to the introduction of the architecture, although the amount of Code has increased, however, as the boundaries are very clear, all types of responsibilities are very clear and single, and later expansion will make maintenance easier.

 

Follow my Sina Weibo website to learn more about Android development!
Focus on science and technology critics, learn about science and technology, innovation, education, and maximize human wisdom and imagination!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.