MVP+retrofit+rxjava+Knife的简单使用
2017-02-28 15:31
393 查看
最近学习了挺多东西,所以想写个demo把最近所学的全都用到,于是就有了这篇博客,这个demo实现的功能特别简单,就是一个查询天气,并且放到textview及recyclerview上显示出来,用的mvp设计框架,也是这两天才稍微看懂的东西,如果有错,还请各路大佬指出,那么废话不多说,先上效果图
从图中能看出有以下功能:
1. 显示progress
2. 隐藏progress
3. 请求数据成功或失败弹出toast提示
4. 将获取到的数据设置到TextView上
5. 将获取到的数据设置到recyclerview上
6. 如果查询出错清空所有的数据
确定了功能那么就是如何实现了,根据mvp的思想,V层只负责初始化view,并将view层接收到的数据(即EditText等)传递到P层,P层再传递给M层,让M层操作数据,包括存储和耗时操作等,然后M层再将数据传回给P层,P层来更新UI,说得再明白点,mvp就是面向接口,那么m,v,p层的接口该怎么写呢?很简单,根据上面我们列出的功能来写相应的接口,直接来看代码:
那么现在V层,也就是Activity只需要实现这个接口即可,看代码:
这里注意一下,我在onCreate方法中实例化了P层,原因就是要让P层拿到V层的实例,这样才能让P层去操作UI,那么P层需要做哪些操作呢,前面说了,M层去操作数据,P层操作UI,再看看我们的效果图,V层获取到了EditText输入的字符串,并且点击查询后获取到了相应的数据,现在要做的,就是把V层获取到的数据传递给M层,让M层去做耗时操作,但是MVP模式,V层是不能直接跟M层进行交互的,怎么办?很简单,我们还有P层没用到,P层的作用就是V层和M层的桥梁,让V层把数据通过P层传递给M层即可,具体怎么做?我们再来分析一下,V层需要传递数据给M层,那么P层就需要一个方法,来接收V层的数据,这个方法就是点击查询按钮后要执行的方法,那么P层现在要做的工作就很简单了,let
me show you code:
接下来在定义一个类去实现该接口
有同学就要问了,model.getWeather又是从哪里来的方法,都是什么鬼,不要急,前面说了,P层需要一个方法来接收V层传递过来数据,然后才能让P层把数据传递给M层,那model.getWeather肯定就是M层的方法了,没错,M层需要做耗时操作,而具体要查询哪一个城市的天气数据,就是从V层传递过来的,逻辑是不是一下就通了,再来分析下M层,M层需要的就是耗时操作,那么耗时操作就有两种可能:
1、请求成功
2、请求失败
所以我们M层的接口写成这样:
现在万事具备,就剩个M层的类来实现这个接口就行了,但是,先暂停一下,看看我们的标题,基于retrofit+rxjava,前面一直没用,当然就是在这个时候来用的,先给个完整的URL,现在来看看retrofit用来实现get请求的接口:
ac84
但是在M层存储好说,怎么在P层取出来呢,如果两个类持有的不是同一个对象,那P层肯定是取不出数据的,很简单,有什么需求就写什么接口,P层需要M层存储的bean类,那么我们在M层的接口再写个getBean的方法,然后让M层去实现不就行了,P层拿到M层的实例直接调用方法就可以拿到我们想要的bean类了,所以完整的M层接口代码:
recyclerview的adapter非常简单,就不贴出来了,有兴趣的话就下载源码自己看看吧,欢迎各位大佬提出建议
github地址
demo源码
从图中能看出有以下功能:
1. 显示progress
2. 隐藏progress
3. 请求数据成功或失败弹出toast提示
4. 将获取到的数据设置到TextView上
5. 将获取到的数据设置到recyclerview上
6. 如果查询出错清空所有的数据
确定了功能那么就是如何实现了,根据mvp的思想,V层只负责初始化view,并将view层接收到的数据(即EditText等)传递到P层,P层再传递给M层,让M层操作数据,包括存储和耗时操作等,然后M层再将数据传回给P层,P层来更新UI,说得再明白点,mvp就是面向接口,那么m,v,p层的接口该怎么写呢?很简单,根据上面我们列出的功能来写相应的接口,直接来看代码:
public interface IMainActivity { //显示progress void showProgress(); //隐藏progress void hideProgress(); /* * 设置文本 * @param temperaturestr:今日温度,@param coldstr:今日建议,@param citystr:城市 * @param yesterdayflstr:昨日风力,@param yesterdayfxstr:昨日风向,@param yesterdayhighstr:昨日最高温 * @param yesterdaylowstr:昨日最低温,@param yesterdaytypestr:昨日天气类型,@param yesterdaydatestr:昨日时间 * * */ void setText(String temperaturestr, String coldstr, String citystr, String yesterdayflstr, String yesterdayfxstr, String yesterdayhighstr, String yesterdaylowstr, String yesterdaytypestr, String yesterdaydatestr); //设置item void setItem(MyAdapter adapter); //Toast提示 void showMsg(String msg); //输入错误时清空textview,recyclerview的item void clearAll(); }
那么现在V层,也就是Activity只需要实现这个接口即可,看代码:
public class MainActivity extends Activity implements IMainActivity { @BindView(R.id.temperature) TextView temperature; @BindView(R.id.rv) RecyclerView rv; @BindView(R.id.citykey) EditText citykey; @BindView(R.id.query) Button query; @BindView(R.id.progress) ProgressBar progress; private WeatherPresenter weatherPresenter; //初始化控件,并new出P层实例 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); weatherPresenter = new WeatherPresenter(this); } //点击监听,用P层实例去调用请求数据的接口 @OnClick(R.id.query) void query() { if (citykey.getText().toString().equals("")) { citykey.setError("不能为空"); } weatherPresenter.validateCredentials(citykey.getText().toString()); } @Override public void showProgress() { progress.setVisibility(View.VISIBLE); } @Override public void hideProgress() { progress.setVisibility(View.GONE); } @Override public void setText(String temperaturestr, String coldstr, String citystr, String yesterdayflstr, String yesterdayfxstr, String yesterdayhighstr, String yesterdaylowstr, String yesterdaytypestr, String yesterdaydatestr) { temperature.setText("城市:" + citystr + "\n" + "今日温度:" + temperaturestr + "\n" + "今日建议:" + coldstr + "\n" + "昨日时间:" + yesterdaydatestr + "\n" + "昨日天气:" + yesterdaytypestr + "\n" + "昨日最" + yesterdayhighstr + "\n" + "昨日最" + yesterdaylowstr + "\n" + "昨日风力:" + yesterdayflstr + "\n" + "昨日风向:" + yesterdayfxstr ); } //设置适配器,显示recyclerview,adapter由P层传回 @Override public void setItem(MyAdapter adapter) { rv.setLayoutManager(new LinearLayoutManager(this)); rv.setAdapter(adapter); } @Override public void showMsg(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } @Override public void clearAll() { rv.setAdapter(null); temperature.setText(""); }
这里注意一下,我在onCreate方法中实例化了P层,原因就是要让P层拿到V层的实例,这样才能让P层去操作UI,那么P层需要做哪些操作呢,前面说了,M层去操作数据,P层操作UI,再看看我们的效果图,V层获取到了EditText输入的字符串,并且点击查询后获取到了相应的数据,现在要做的,就是把V层获取到的数据传递给M层,让M层去做耗时操作,但是MVP模式,V层是不能直接跟M层进行交互的,怎么办?很简单,我们还有P层没用到,P层的作用就是V层和M层的桥梁,让V层把数据通过P层传递给M层即可,具体怎么做?我们再来分析一下,V层需要传递数据给M层,那么P层就需要一个方法,来接收V层的数据,这个方法就是点击查询按钮后要执行的方法,那么P层现在要做的工作就很简单了,let
me show you code:
public interface IWeatherPresenter { //请求数据 void validateCredentials(String citykey); }
接下来在定义一个类去实现该接口
//进行数据请求,请求时显示progress @Override public void validateCredentials(String citykey) { view.showProgress(); model.getWeather(citykey, this); }
有同学就要问了,model.getWeather又是从哪里来的方法,都是什么鬼,不要急,前面说了,P层需要一个方法来接收V层传递过来数据,然后才能让P层把数据传递给M层,那model.getWeather肯定就是M层的方法了,没错,M层需要做耗时操作,而具体要查询哪一个城市的天气数据,就是从V层传递过来的,逻辑是不是一下就通了,再来分析下M层,M层需要的就是耗时操作,那么耗时操作就有两种可能:
1、请求成功
2、请求失败
所以我们M层的接口写成这样:
public interface IWeatherModel { interface OnLinstener { //请求失败 void onFailed(); //请求成功 void onSuccess(); } //请求数据 void getWeather(String citykey, OnLinstener linstener); }
现在万事具备,就剩个M层的类来实现这个接口就行了,但是,先暂停一下,看看我们的标题,基于retrofit+rxjava,前面一直没用,当然就是在这个时候来用的,先给个完整的URL,现在来看看retrofit用来实现get请求的接口:
public interface APIService { @GET("/weather_mini") Observable<Bean> getApi(@Query("citykey") String citykey); }有同学要问,返回的Observable是个啥,这个是rxjava特有的,我能力不足,只限于能用的阶段。。还不能很好的解释其中的原理,有兴趣的可以去看看这位大佬rxjava的系列文章,接下来是用于解析json的bean类,太长就不放了。。有兴趣可以下载源码看看,现在,要开始写M层的逻辑了,M层就是用来操作数据的,说白了就是耗时操作,存储数据,看代码:
public class WeatherModel implements IWeatherModel { private static final String TAG = "WeatherModel"; private Retrofit retrofit; private OkHttpClient client; private MyBean bean; //进行耗时操作,访问数据 @Override public void getWeather(String citykey, final OnLinstener linstener) { Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request().newBuilder().build(); return chain.proceed(request); } }; client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); retrofit = new Retrofit.Builder() .baseUrl("http://wthrcdn.etouch.cn") .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); APIService api = retrofit.create(APIService.class); api.getApi(citykey) .subscribeOn(Schedulers.io())//在io线程执行 .observeOn(AndroidSchedulers.mainThread())//执行完成后回调给UI线程 .subscribe(new Observer<Bean>() { @Override public void onSubscribe(Disposable d) { Log.i(TAG, "onSubscribe: "); } @Override public void onNext(Bean value) { if (value.getDesc().equals("OK")) { bean = new MyBean(); bean.setWendu(value.getData().getWendu()); bean.setGanmao(value.getData().getGanmao()); bean.setCity(value.getData().getCity()); bean.setYesterdayfl(value.getData().getYesterday().getFl()); bean.setYesterdayfx(value.getData().getYesterday().getFx()); bean.setYesterdayhigh(value.getData().getYesterday().getHigh()); bean.setYesterdaylow(value.getData().getYesterday().getLow()); bean.setYesterdaytype(value.getData().getYesterday().getType()); bean.setYesterdaydate(value.getData().getYesterday().getDate()); bean.setList(value.getData().getForecast()); bean.setMsg("请求数据正确,请稍后"); linstener.onSuccess(); Log.i(TAG, "onNext: "); } else { bean = new MyBean(); bean.setMsg("请求数据错误,请重新输入"); linstener.onFailed(); } } @Override public void onError(Throwable e) { linstener.onFailed(); Log.e(TAG, "onError: "); } @Override public void onComplete() { Log.i(TAG, "onComplete: "); } }); }我写了另一个bean类来存储所有数据,这样P层才能直接把数据拿来用,
ac84
但是在M层存储好说,怎么在P层取出来呢,如果两个类持有的不是同一个对象,那P层肯定是取不出数据的,很简单,有什么需求就写什么接口,P层需要M层存储的bean类,那么我们在M层的接口再写个getBean的方法,然后让M层去实现不就行了,P层拿到M层的实例直接调用方法就可以拿到我们想要的bean类了,所以完整的M层接口代码:
public interface IWeatherModel { interface OnLinstener { //请求失败 void onFailed(); //请求成功 void onSuccess(); } //请求数据 void getWeather(String citykey, OnLinstener linstener); //获取bean类 MyBean getBean(); }完整的M层代码:
public class WeatherModel implements IWeatherModel { private static final String TAG = "WeatherModel"; private Retrofit retrofit; private OkHttpClient client; private MyBean bean; //进行耗时操作,访问数据 @Override public void getWeather(String citykey, final OnLinstener linstener) { Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request().newBuilder().build(); return chain.proceed(request); } }; client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); retrofit = new Retrofit.Builder() .baseUrl("http://wthrcdn.etouch.cn") .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .client(client) .build(); APIService api = retrofit.create(APIService.class); api.getApi(citykey) .subscribeOn(Schedulers.io())//在io线程执行 .observeOn(AndroidSchedulers.mainThread())//执行完成后回调给UI线程 .subscribe(new Observer<Bean>() { @Override public void onSubscribe(Disposable d) { Log.i(TAG, "onSubscribe: "); } @Override public void onNext(Bean value) { if (value.getDesc().equals("OK")) { bean = new MyBean(); bean.setWendu(value.getData().getWendu()); bean.setGanmao(value.getData().getGanmao()); bean.setCity(value.getData().getCity()); bean.setYesterdayfl(value.getData().getYesterday().getFl()); bean.setYesterdayfx(value.getData().getYesterday().getFx()); bean.setYesterdayhigh(value.getData().getYesterday().getHigh()); bean.setYesterdaylow(value.getData().getYesterday().getLow()); bean.setYesterdaytype(value.getData().getYesterday().getType()); bean.setYesterdaydate(value.getData().getYesterday().getDate()); bean.setList(value.getData().getForecast()); bean.setMsg("请求数据正确,请稍后"); linstener.onSuccess(); Log.i(TAG, "onNext: "); } else { bean = new MyBean(); bean.setMsg("请求数据错误,请重新输入"); linstener.onFailed(); } } @Override public void onError(Throwable e) { linstener.onFailed(); Log.e(TAG, "onError: "); } @Override public void onComplete() { Log.i(TAG, "onComplete: "); } }); }P层完整的代码:
//将保存的MyBean类返回给P层
@Override
public MyBean getBean() {
return this.bean;
}
}
public class WeatherPresenter implements IWeatherPresenter, IWeatherModel.OnLinstener {
private IMainActivity view;
private IWeatherModel model;
private List<Bean.Data.forecast> list;
//构造器,需要传入v层实例,并new一个m层实例,以达到让P层实现桥梁的作用
public WeatherPresenter(IMainActivity view) {
this.view = view;
this.model = new WeatherModel();
}
//进行数据请求,请求时显示progress @Override public void validateCredentials(String citykey) { view.showProgress(); model.getWeather(citykey, this); }
//数据请求失败时隐藏progress
@Override
public void onFailed() {
view.clearAll();
MyBean bean = model.getBean();
view.showMsg(bean.getMsg());
view.hideProgress();
}
//数据请求成功后将数据显示在控件上,且在请求成功后隐藏progress
@Override
public void onSuccess() {
MyBean bean = model.getBean();
if (bean.getMsg().equals("请求数据正确,请稍后")) {
view.showMsg(bean.getMsg());
view.setText(bean.getWendu(), bean.getGanmao(), bean.getCity(), bean.getYesterdayfl(),
bean.getYesterdayfx(), bean.getYesterdayhigh(), bean.getYesterdaylow(),
bean.getYesterdaytype(), bean.getYesterdaydate());
list = bean.getList();
MyAdapter adapter = new MyAdapter((Context) view, list);
view.setItem(adapter);
view.hideProgress();
}
}
}
recyclerview的adapter非常简单,就不贴出来了,有兴趣的话就下载源码自己看看吧,欢迎各位大佬提出建议
github地址
demo源码
相关文章推荐
- 使用RxJava+Retrofit+MVP+Glide开发一个简单的新闻客户端
- 使用Retrofit+RxJava搭建简单的MVP网络请求框架
- 进阶之路:MVP+Retrofit+RxJava组合使用
- 设计模式笔记之四:MVP+Retrofit+RxJava组合使用
- 使用MVP+Retrofit+rxjava让你的代码更简洁
- [Android]RxJava的简单介绍和基本使用(二):retrofit2的简单介绍
- 浅谈Android MVP设计模式(简单结合RxJava+Retrofit)
- Rxjava+Retrofit+Mvp的使用实例(基于retrofit2.1.0)
- retrofit2+RxJava简单使用
- 天气预报项目学习总结(- ButterKnife - Retrofit 2.0(okhttp) - Rxjava - Jackson - Ormlite - Mosby简单使用总结)
- Retrofit和Rxjava的简单使用
- RxJava简单使用、模仿访问服务器获取数据更新界面-基于mvp架构
- 简单地使用下RxJava + Retrofit
- Material Design 风格 结合使用 Retrofit RxJava Jsoup Mvp 模式的一款资讯类 学习 app
- 浅学开发模式----MVP模式和使用Retrofit和RxJava使用
- Retrofit2.0+RxJava+MVP+Bmob的使用
- 简单入门使用Retrofit+ rxjava 下载图片
- Retrofit 和 RxJava的简单使用以及简单封装
- Mvp-Retrofit-Rxjava-Rxbus的初步使用
- 使用MVP+Retrofit+RxJava实现的的Android Demo (上)使用Nuclues库实现MVP