美文网首页架构与框架
《安卓-深入浅出MVVM教程》应用篇-02 Repository

《安卓-深入浅出MVVM教程》应用篇-02 Repository

作者: IT天宇 | 来源:发表于2017-10-23 23:58 被阅读802次

    简介

    背景

    这几年 MVP 架构在安卓界非常流行,几乎已经成为主流框架,它让业务逻辑 和 UI操作相对独立,使得代码结构更清晰。


    MVVM 在前端火得一塌糊涂,而在安卓这边却基本没见到几个人在用,看到介绍 MVVM 也最多是讲 DataBinding 或 介绍思想的。偶尔看到几篇提到应用的,还是对谷歌官网的Architecture Components 文章的翻译。

    相信大家看别人博客或官方文档的时候,总会碰到一些坑。要么入门教程写得太复杂(无力吐槽,前面写一堆原理,各种高大上的图,然并卵,到实践部分一笔带过,你确定真的是入门教程吗)。要么就是简单得就是一个 hello world,然后就没有下文了(看了想骂人)。


    实在看不下去的我,决定插手你的人生。

    目录

    《安卓-深入浅出MVVM教程》大致分两部分:应用篇、原理篇。
    采用循序渐进方式,内容深入浅出,符合人类学习规律,希望大家用最少时间掌握 MVVM。

    应用篇:

    01 Hello MVVM (快速入门)
    02 Repository (数据仓库)
    03 Cache (本地缓存)
    04 State Lcee (加载/空/错误/内容视图)
    05 Simple Data Source (简单的数据源)
    06 Load More (加载更多)
    07 DataBinding (数据与视图绑定)
    08 RxJava2
    09 Dragger2
    10 Abstract (抽象)
    11 Demo (例子)
    12-n 待定(欢迎 github 提建议)

    原理篇

    01 MyLiveData(最简单的LiveData)
    02-n 待定(并不是解读源码,那样太无聊了,打算带你从0撸一个 Architecture)

    关于提问

    本人水平和精力有限,如果有大佬发现哪里写错了或有好的建议,欢迎在本教程附带的 github仓库 提issue。
    What?为什么不在博客留言?考虑到国内转载基本无视版权的情况,一般来说你都不是在源出处看到这篇文章,所以留言我也一般是看不到的。

    教程附带代码

    https://github.com/ittianyu/MVVM

    应用篇放在 app 模块下,原理篇放在 implementation 模块下。
    每一节代码采用不同包名,相互独立。

    前言

    上一节我们讲了一个简单的 MVVM 案例,然而 Model 这边数据是伪造的,好吧,这一节就给大家来一个真实的数据源。

    Model

    还是上节课那个案例,只不过换了数据源。

    api

    下面是 github 的 api,请求接口返回 json 数据。

    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": "octocat@github.com",
      "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"
    }
    

    准备

    为了请求和解析数据,这里采用大家最熟悉的 retrofit 和 gson。

    // retrofit
    compile 'com.squareup.retrofit2:retrofit:2.3.0'
    compile 'com.squareup.retrofit2:converter-gson:2.3.0'
    

    记得加上网络访问权限

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

    Bean

    然后我们重新定义一下 bean。(我这是通过 GsonFormatter 插件生成的)

    
    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...
    }
    
    

    Utils

    为了便于使用,封装一个 RetrofitFactory,记得加上 gson 的 转换器。

    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;
        }
    }
    

    Api 接口

    定义好 Api 请求接口

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

    数据源

    为了方便 ViewModel 调用,我们返回 LiveData 数据。
    其实也很简单,就是做了个数据适配器,知道 retrofit 的一下就能看明白。在数据请求成功时,往 LiveData 里写入数据。

    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;
        }
    }
    
    

    ViewModel

    因为数据源有所改动,在拿到 LiveData 时,需要传入一个 username 参数,所以 ViewModel 也得做相应的变化。

    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;
        }
    }
    

    View

    因为 ViewModel 多加了一个参数,所以,Activity 也得改动

    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);
            }
        });
    }
    

    总结

    这一节主要是加入了 retrofit,如果你之前熟悉这个库,那本节对你几乎没有难度。你需要重点掌握的是 retrofit 返回的数据和 LiveData 之间的转换。

    这样就结束了?数据缓存怎么做?
    慌不要慌,请听下回分解。

    相关文章

      网友评论

        本文标题:《安卓-深入浅出MVVM教程》应用篇-02 Repository

        本文链接:https://www.haomeiwen.com/subject/rwizuxtx.html