# LookLook剖析,架构概述——MVP、Retrofit+RxJava

*前言：* *学习LookLook这个开源项目的初衷是学习MVP架构，因为自己已经块学了一年的Android，可是对架构一直没有什么概念，而且平时自己编项目时总是没有框架。写到哪里，就封装到哪里，照着一些接口自己总是瞎写写，收获甚微，代码乱，所以出现最多的情况就是写不下去了，代码不仅没法扩展，也没法修改。*

项目地址：<https://github.com/xinghongfei/LookLook>

LookLook的最大特点就是他的MVP架构，所以让我们先从MVP架构看起： MVP：Model、View、Presenter 简单来说就是将应用分为三层，降低耦合性：数据（Bean）、视图（Activity、Fragment）、适配器,并且View和Model分别与Presenter交互，View和Model不交互 哈哈，怎么听着这么像AdapterView呢（悄悄告诉你，RecyclerView的适配器里也有观察者模式的踪影哦）！

让我们来看一下LookLook： ![^\_^](https://github.com/yangsx95/notes/blob/master/front-end/android/LookLook%E5%89%96%E6%9E%90,%E6%9E%B6%E6%9E%84%E6%A6%82%E8%BF%B0%E2%80%94%E2%80%94MVP%E3%80%81Retrofit+RxJava.assets/20161031203331645.png) ps:初学UML，图画的不标准，还请见谅！！！

我们可以先构想一下数据刷新的整个过程: 用户触发加载刷新等操作 --> View通知Presenter更新数据 --> Presenter通知Model获取数据 --> 加载完毕 --> Model 通知Presenter数据发生改变 --> Presenter通知View更新界面

View和Presenter的交互： View持有Presenter的引用，当用户触发加载操作的时候，调用Presenter的getData()方法通知数据更新。 当数据更新完成后，presenter会在内部拿着View的引用来进行UI操作(updateMeiziData()...)。

Model和Presenter的交互方式很特殊，采用了**RxJava+Retrofit**的方式： 上代码：

```java
public interface ZhihuApi {

    @GET("/api/4/news/latest")
    Observable<ZhihuDaily> getLastDaily();

    @GET("/api/4/news/before/{date}")
    Observable<ZhihuDaily> getTheDaily(@Path("date") String date);

    @GET("/api/4/news/{id}")
    Observable<ZhihuStory> getZhihuStory(@Path("id") String id);
}
```

ApiManager:这里我只贴部分代码

```java
public class ApiManage {
	public ZhihuApi getZhihuApiService() {
        if (zhihuApi == null) {
            synchronized (zhihuMonitor) {
                if (zhihuApi == null) {
                    zhihuApi = new Retrofit.Builder()
                            .baseUrl("http://news-at.zhihu.com")
                            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                            // 注意这里添加RxJavaCallAdapterFactory
                            .client(client)
                            .addConverterFactory(GsonConverterFactory.create())
                            .build().create(ZhihuApi.class);
                }
            }
        }
        return zhihuApi;
    }
}
```

这样通过这个方法就可以获得RxJava的被观察者了，然后只要在Presenter中向这个被观察者中添加几个随从（观察着），就可以随时获悉数据的变化情况

```java
public class ZhihuPresenterImpl extends BasePresenterImpl implements IZhihuPresenter {

	// presenter持有view的引用
    private IZhihuFragment mZhihuFragment;
    private CacheUtil mCacheUtil;
    private Gson gson = new Gson();

    public ZhihuPresenterImpl(Context context,IZhihuFragment zhihuFragment) {

        mZhihuFragment = zhihuFragment;
        mCacheUtil = CacheUtil.get(context);
    }

    @Override
    public void getLastZhihuNews() {
        mZhihuFragment.showProgressDialog();
        Subscription subscription = ApiManage.getInstance().getZhihuApiService().getLastDaily()
                .map(new Func1<ZhihuDaily, ZhihuDaily>() { //添加了观察者，当这些观察者发现数据状态有变时，就会使用View的接口来更新UI
                    @Override
                    public ZhihuDaily call(ZhihuDaily zhihuDaily) {
                        String date = zhihuDaily.getDate();
                        for (ZhihuDailyItem zhihuDailyItem : zhihuDaily.getStories()) {
                            zhihuDailyItem.setDate(date);
                        }
                        return zhihuDaily;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<ZhihuDaily>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        mZhihuFragment.hidProgressDialog();
                        mZhihuFragment.showError(e.getMessage());
                    }

                    @Override
                    public void onNext(ZhihuDaily zhihuDaily) {
                        mZhihuFragment.hidProgressDialog();
                        mCacheUtil.put(Config.ZHIHU, gson.toJson(zhihuDaily));
                        mZhihuFragment.updateList(zhihuDaily);
                    }
                });
        addSubscription(subscription);
    }
    
    @Override
    public void getTheDaily(String date) {
        Subscription subscription = ApiManage.getInstance().getZhihuApiService().getTheDaily(date)
                .map(new Func1<ZhihuDaily, ZhihuDaily>() {
                    @Override
                    public ZhihuDaily call(ZhihuDaily zhihuDaily) {
                        String date = zhihuDaily.getDate();
                        for (ZhihuDailyItem zhihuDailyItem : zhihuDaily.getStories()) {
                            zhihuDailyItem.setDate(date);
                        }
                        return zhihuDaily;
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<ZhihuDaily>() {
                    @Override
                    public void onCompleted() {
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        mZhihuFragment.hidProgressDialog();
                        mZhihuFragment.showError(e.getMessage());
                    }

                    @Override
                    public void onNext(ZhihuDaily zhihuDaily) {
                        mZhihuFragment.hidProgressDialog();
                        mZhihuFragment.updateList(zhihuDaily);
                    }
                });
        addSubscription(subscription);
    }

    @Override
    public void getLastFromCache() {
        if (mCacheUtil.getAsJSONObject(Config.ZHIHU) != null) {
            ZhihuDaily zhihuDaily = gson.fromJson(mCacheUtil.getAsJSONObject(Config.ZHIHU).toString(), ZhihuDaily.class);
            mZhihuFragment.updateList(zhihuDaily);
        }
    }
}

```

是不是很简单呢？MVP也基本就是这个样子，很有利于后期的维护和代码的修改，至少思路还是很清晰的！！
