Introduction to the

background

The MVP architecture has been very popular in the Android world for a few years and has become a mainstream framework. It makes the business logic and UI operations relatively independent and makes the code structure clearer.






MVVM is a big hit on the front end, but on the Android side, you don’t see a lot of people using it, and the introduction of MVVM is mostly about DataBinding or introducing ideas. The occasional mention of apps is a translation of Architecture Components on Google’s website.

I believe that when you read other people’s blogs or official documents, there will always be some pits. Or the introductory tutorial is too complicated (a bunch of principles and fancy diagrams are written in front of you, but they don’t really work, and are you sure it’s really an introductory tutorial?). Or it could be as simple as a “Hello World” and nothing more.






I couldn’t stand it, so I decided to intervene in your life.

directory

“Android – simple MVVM tutorial” is roughly divided into two parts: application, principle. Adopt step by step way, the content is simple, in line with the law of human learning, hope we use the least time to master MVVM.

Application of article:

01 Hello MVVM (Quick Start) 02 Repository 03 Cache 04 State Lcee (Load/null/error/Content view) 05 Simple Data Source 06 Load More 07 DataBinding 08 RxJava2 09 Dragger2 10 Abstract 11 Demo 12-N TBD

The principle of article

01 MyLiveData (the simplest LiveData) 02-n to be determined

About the questions

I have limited ability and energy, if you find something wrong or have a good suggestion, feel free to make an issue in the Github repository that accompanies this tutorial. What? Why not blog? Taking into account the domestic reproduction of the basic disregard of copyright, generally speaking, you are not in the source to see this article, so I generally can not see the message.

Tutorial code

Github.com/ittianyu/MV…

The application section is placed under the APP module, and the principle section is placed under the Implementation module. Each section of code uses a different package name and is independent of each other.

preface

In the last video we looked at a simple MVVM case, but the Model data was faked. Ok, this video is going to give you a real data source.

Model

It’s the same case as last time, but with a different data source.

api

Here is github’s API, requesting that the interface return JSON data.

HOST https://api.github.com GET /users/:username { "login": "octocat", "id": 1, "avatar_url": "https://github.com/images/error/octocat_happy.gif", "gravatar_id": "", "url": "https://api.github.com/users/octocat", "html_url": "https://github.com/octocat", "followers_url": "https://api.github.com/users/octocat/followers", "following_url": "https://api.github.com/users/octocat/following{/other_user}", "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", "organizations_url": "https://api.github.com/users/octocat/orgs", "repos_url": "https://api.github.com/users/octocat/repos", "events_url": "https://api.github.com/users/octocat/events{/privacy}", "received_events_url": "https://api.github.com/users/octocat/received_events", "type": "User", "site_admin": false, "name": "monalisa octocat", "company": "GitHub", "blog": "https://github.com/blog", "location": "San Francisco", "email": "[email protected]", "hireable": false, "bio": "There once was..." , "public_repos": 2, "public_gists": 1, "followers": 20, "following": 0, "created_at": "2008-01-14T04:33:35Z", "updated_at": "2008-01-14T04:33:35Z" }Copy the code

To prepare

To request and parse data, the most familiar retrofit and Gson are used.

/ / retrofit the compile 'com. Squareup. Retrofit2: retrofit: 2.3.0' compile 'com. Squareup. Retrofit2: converter - gson: 2.3.0'Copy the code

Be sure to add Internet access

<uses-permission android:name="android.permission.INTERNET"/>
Copy the code

Bean

Then let’s redefine the bean. (I generated this using the GsonFormatter plugin)

public class User implements Serializable { private String login; private int id; private String avatar_url; private String gravatar_id; private String url; private String html_url; private String followers_url; private String following_url; private String gists_url; private String starred_url; private String subscriptions_url; private String organizations_url; private String repos_url; private String events_url; private String received_events_url; private String type; private boolean site_admin; private String name; private Object company; private String blog; private Object location; private Object email; private boolean hireable; private Object bio; private int public_repos; private int public_gists; private int followers; private int following; private String created_at; private String updated_at; / /... getter setter and toString... }Copy the code

Utils

For ease of use, package a RetrofitFactory, remember to add gson’s converter.

public class RetrofitFactory { private static OkHttpClient client; private static Retrofit retrofit; private static final String HOST = "https://api.github.com"; static { client = new OkHttpClient.Builder() .connectTimeout(9, TimeUnit.SECONDS) .build(); retrofit = new Retrofit.Builder() .baseUrl(HOST) .client(client) .addConverterFactory(GsonConverterFactory.create()) .build(); } public static Retrofit getInstance() { return retrofit; }}Copy the code

Api interface

Define the Api request interface

public interface UserApi {
    @GET("/users/{username}")
    Call<User> queryUserByUsername(@Path("username") String username);
}
Copy the code

The data source

To facilitate the ViewModel call, we return the LiveData data. In fact, it is very simple, just make a data adapter, know retrofit will be able to understand. Write data to LiveData when the data request succeeds.

public class UserRepository { private static final UserRepository instance = new UserRepository(); private UserRepository() { } public static UserRepository getInstance() { return instance; } private UserApi userApi = RetrofitFactory.getInstance().create(UserApi.class); public LiveData<User> getUser(String username) { final MutableLiveData<User> user = new MutableLiveData<>(); userApi.queryUserByUsername(username) .enqueue(new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { user.setValue(response.body()); } @Override public void onFailure(Call<User> call, Throwable t) { t.printStackTrace(); }}); return user; }}Copy the code

ViewModel

Because the data source has changed, we need to pass in a username parameter when we get the LiveData, so the ViewModel has to change accordingly.

public class UserViewModel extends ViewModel { private UserRepository userRepository = UserRepository.getInstance(); private LiveData<User> user; public LiveData<User> getUser(String username) { if (null == user) user = userRepository.getUser(username); return user; }}Copy the code

View

Because the ViewModel adds one more parameter, the Activity needs to change as well

private void initData() { userViewModel = ViewModelProviders.of(this).get(UserViewModel.class); userViewModel.getUser("ittianyu").observe(this, new Observer<User>() { @Override public void onChanged(@Nullable User user) { updateView(user); }}); }Copy the code

conclusion

This section is mostly retrofit, and if you’re familiar with the library, this section should be pretty easy for you. What you need to focus on is the conversion between the data returned by Retrofit and LiveData.

Is that the end of it? What about data caching? Don’t panic, listen to the next breakdown.