前言: 学习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: ps:初学UML,图画的不标准,还请见谅!!!
我们可以先构想一下数据刷新的整个过程: 用户触发加载刷新等操作 --> View通知Presenter更新数据 --> Presenter通知Model获取数据 --> 加载完毕 --> Model 通知Presenter数据发生改变 --> Presenter通知View更新界面
View和Presenter的交互: View持有Presenter的引用,当用户触发加载操作的时候,调用Presenter的getData()方法通知数据更新。 当数据更新完成后,presenter会在内部拿着View的引用来进行UI操作(updateMeiziData()...)。
Model和Presenter的交互方式很特殊,采用了RxJava+Retrofit的方式: 上代码:
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:这里我只贴部分代码
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中向这个被观察者中添加几个随从(观察着),就可以随时获悉数据的变化情况
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也基本就是这个样子,很有利于后期的维护和代码的修改,至少思路还是很清晰的!!