Android MVP +Retrofit+RxJava
来源:互联网 发布:mac npm安装webpack 编辑:程序博客网 时间:2024/04/30 20:23
MVP +Retrofit+RxJava这三个结合使用好像已经火了一段时间了,有时候我们只是学会了使用,却不能深刻理解。之前写过两篇关于mvp的使用跟理解的文章。感兴趣的可以看一下,这篇文章关于mvp就不多解释了。这里只说最简单的MVP +Retrofit+RxJava三者结合使用的demo,因为说多了一方面不容易消化一方面容易乱,一步一步的消化之后才能深入理解,而且具体的一些变化还要根据项目尽心修改。
http://blog.csdn.net/danfengw/article/details/51829746
http://blog.csdn.net/danfengw/article/details/51902665
MVP
再简单说一下,M:model 数据逻辑和实体模型 V:view 指Activity负责页面显示与交互 P:presenter model与view的接口持有者,减少了Model与View的联系,降低了耦合度。
Model
demo请求地址 http://www.weather.com.cn/adat/sk/101010100.html
请求数据:
{"weatherinfo":{"city":"北京","cityid":"101010100","temp":"10","WD":"东南风","WS":"2级","SD":"26%","WSE":"2","time":"10:25","isRadar":"1","Radar":"JC_RADAR_AZ9010_JB","njd":"暂无实况","qy":"1012"}}
model生成有种简单的方法:
直接用AndroidStudio的GsonFormat插件就可以生成File——setting——Browser reponsitorise
安装一下,重启AS,创建一个类比如下面的WeatherModel 类,然后alt+insert快捷键选择GosonFormat然后将上面的json串复制进去,就可以自动生成了,大概如下所示。需要注意的是,此时
你生成的类中可能并没有Weatherinfo 这个内部类,可能是其他的类名,如果不是Weatherinfo 则需要自己手动修改为Weatherinfo 这个类名,如果不注意这一点,后面你可能就掉坑里怎么都出不来了,这是什么原因呢?这是由于后面我们要结合retrofit进行网络请求。
public class WeatherModel { /** * weatherinfo : {"city":"北京","cityid":"101010100","temp":"10","WD":"东南风","WS":"2级","SD":"26%","WSE":"2","time":"10:25","isRadar":"1","Radar":"JC_RADAR_AZ9010_JB","njd":"暂无实况","qy":"1012"} */ private Weatherinfo weatherinfo; public Weatherinfo getWeatherinfo() { return weatherinfo; } public void setWeatherinfo(Weatherinfo weatherinfo) { this.weatherinfo = weatherinfo; } public static class Weatherinfo { /** * city : 北京 * cityid : 101010100 * temp : 10 * WD : 东南风 * WS : 2级 * SD : 26% * WSE : 2 * time : 10:25 * isRadar : 1 * Radar : JC_RADAR_AZ9010_JB * njd : 暂无实况 * qy : 1012 */ private String city; private String cityid; private String temp; private String WD; private String WS; private String SD; private String WSE; private String time; private String isRadar; private String Radar; private String njd; private String qy; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getCityid() { return cityid; } public void setCityid(String cityid) { this.cityid = cityid; } public String getTemp() { return temp; } public void setTemp(String temp) { this.temp = temp; } public String getWD() { return WD; } public void setWD(String WD) { this.WD = WD; } public String getWS() { return WS; } public void setWS(String WS) { this.WS = WS; } public String getSD() { return SD; } public void setSD(String SD) { this.SD = SD; } public String getWSE() { return WSE; } public void setWSE(String WSE) { this.WSE = WSE; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } public String getIsRadar() { return isRadar; } public void setIsRadar(String isRadar) { this.isRadar = isRadar; } public String getRadar() { return Radar; } public void setRadar(String Radar) { this.Radar = Radar; } public String getNjd() { return njd; } public void setNjd(String njd) { this.njd = njd; } public String getQy() { return qy; } public void setQy(String qy) { this.qy = qy; } }}
View
由于Presenter持有的是View的接口所以View的接口也就必不可少
View接口
/** * 只作为一个标记 */public interface IView {}
具体的weatherview
public interface WeatherView extends IView{//两个方法进行回调,onsuccess的方法参数根据需要设置 void onSuccess(WeatherModel model); void onError(String res);}
Presenter
由于不确定之后的View究竟是哪个View因此在Presenter中使用泛型。
public class IPresenter<T extends IView> { T mView; //将view绑定防止内存泄露 public void onCreate(T view) { mView = view; } public void onDestroy() { if (mView != null) { mView = null; } }}
具体的presenter
public class WeatherPresenter extends IPresenter<WeatherView> { public void getView(){ //这里进行网络请求获取数据,获取到数据调用weatherview的onsuccess方法 }}
调用
public class DemoActivity extends AppCompatActivity implements WeatherView { TextView mTv; WeatherPresenter mPresenter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.demo_activity); mTv = (TextView) findViewById(R.id.tv); mPresenter=new WeatherPresenter(); mPresenter.onCreate(this); mPresenter.getView(); } @Override public void onSuccess(WeatherModel model) { WeatherModel weatherInfo =model; String str = "" + weatherInfo.getWeatherinfo().getCity() + weatherInfo.getWeatherinfo().getWD(); mTv.setText(str); } @Override public void onError(String res) { }}
小结:
1、Model:学习GsonFormat插件,注意类名一致性
2、View:IView标识类
3、Presenter:持有Model和View接口,上面的model并没有给出接口,我们可以设置Model接口。因为平时我们的请求信息一般都是这种带有 “errno”“msg”和”data”:的
{ "errno": "no", "msg": "成功", "data": { "weatherinfo": { "city": "北京", "cityid": "101010100", "temp": "10", "WD": "东南风", "WS": "2级", "SD": "26%", "WSE": "2", "time": "10:25", "isRadar": "1", "Radar": "JC_RADAR_AZ9010_JB", "njd": "暂无实况", "qy": "1012" } }}
此时可以将给Model写个接口
public class IModel<T> { public String errno; public String msg; public T data;}
Model接口具体思路参考http://blog.csdn.net/lyhhj/article/details/51720296
Retrofit2.0
下面一讲retrofit可能就要跑远了,为了mvp跟retrofit的完整理解就先把retrofit请求部分代码放在这里,后面会有详细介绍。
public class WeatherPresenter extends IPresenter<WeatherView> { public void getView() { Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://www.weather.com.cn/") .addConverterFactory(GsonConverterFactory.create()) .build();// http://www.weather.com.cn/adat/sk/101010100.html WeatherApi apiStores = retrofit.create(WeatherApi.class); Call<WeatherModel> call = apiStores.getWeather("101010100"); call.enqueue(new Callback<WeatherModel>() { @Override public void onResponse(Call<WeatherModel> call, Response<WeatherModel> response) { mView.onSuccess(response.body()); } @Override public void onFailure(Call<WeatherModel> call, Throwable t) { } }); }}
看到这里可以先将mvp+retrofit仔细捋一遍逻辑了。
官网配置
使用
1、Retrofit 网址配置
retrofit的基础配置只配置前半部分http://www.weather.com.cn/后面部分由于带有请求参数,在具体的请求api中进行设置
// http://www.weather.com.cn/adat/sk/101010100.html
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://www.weather.com.cn/") .addConverterFactory(GsonConverterFactory.create()) .build();
2、api
进行URL拼接
public interface WeatherApi{ @GET("adat/sk/{cityId}.html") Call<WeatherModel> getWeather(@Path("cityId") String cityId);}
api请求参数类有2个注意点:
(1)注解请求方式get
retrofit的请求方式当然不会只有get一种方式,具体根据需要使用,比如:
GET-——查找资源
POST——修改资源
PUT——上传文件
DELETE——删除文件
HEAD——之请求页面首部
(2)参数拼接@Path,retrofit除了@Path注解外还有其他的比如:@Query@QueryMap @Body @FormUrlEncoded @Field @Header @Headers
@Query(get请求)
假设请求url为http://www.weather.com.cn/adat/sk?q=a
@GET("adat/sk") Call<WeatherModel> getWeather(@Query("q") String a);
@QueryMap(get请求)
传递参数比较多时
@GET("adat/sk") Call<WeatherModel> getWeather(@QueryMap Map<String,String> a);
@Body(post请求)
假设存在Weather 类,指定一个对象作为Http请求体
@POST("adat/sk") Call<WeatherModel> getWeather(@Body Weather weather);
@Field(post请求)
用于传递表单数据
@POST("user/info") Call<USer> setUserInfo(@Field("username") String username ,@Field("password") String password);
@Header
@POST("adat/sk") Call<WeatherModel> getWeather(@Header("Authorization") String Authorization);
@Headers
@Headers("Cache-Control: max-age=640000") @GET("/tasks") Call<List<Task>> getTasks();
3、异步请求,获取返回值
WeatherApi apiStores = retrofit.create(WeatherApi.class);//异步请求,获取返回值Call<WeatherModel> call = apiStores.getWeather("101010100"); call.enqueue(new Callback<WeatherModel>() { @Override public void onResponse(Call<WeatherModel> call, Response<WeatherModel> response) { mView.onSuccess(response.body()); } @Override public void onFailure(Call<WeatherModel> call, Throwable t) { } });
RxJava
先来看看Rxjava与MVP跟Retrofit结合是怎么使用的,再来介绍Rxjava 的使用及Scheduler 线程控制。
1、要先修改WeatherApi,将返回值类型Call修改为Observable。
public interface WeatherApi{ @GET("adat/sk/{cityId}.html") Observable<WeatherModel> getWeather(@Path("cityId") String cityId);}
2、通过subscribeon对io线程事件订阅监听
Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://www.weather.com.cn/") .addConverterFactory(GsonConverterFactory.create()) .build();// http://www.weather.com.cn/adat/sk/101010100.html WeatherApi apiStores = retrofit.create(WeatherApi.class); Observable<WeatherModel> observable = apiStores.getWeather("101010100"); observable.subscribeOn(Schedulers.io()) //请求数据事件发生在io线程中 .observeOn(AndroidSchedulers.mainThread()) //请求完成后再主线程更新UI .subscribe(new Observer<WeatherModel>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(WeatherModel model) { //请求成功进行回调 mView.onSuccess(model); } @Override public void onError(Throwable e) { //请求发生错误 } @Override public void onComplete() { //所有事件完成,进行相关操作 } });
Rxjava 2.0
Rxjava基本思想是一个观察者模式,所以对Rxjava的理解就少不了观察者(Observer)和被观察者(Observable),此外还有一个subscribe订阅需要理解。
观察者模式:所有的观察者观察一个被观察者,在被观察者发生某些变化时,所有观察者会做出以下反应。
Observable:在观察者模式中称为“被观察者”;
Observer:观察者模式中的“观察者”,可接收Observable发送的数据;
//下面这两个可以暂且不看
subscribe:订阅,观察者与被观察者,通过subscribe()方法进行订阅;
Subscriber:也是一种观察者,在2.0中 它与Observer没什么实质的区别,不同的是 Subscriber要与Flowable(也是一种被观察者)联合使用,该部分内容是2.0新增的,后续文章再介绍。Obsesrver用于订阅Observable,而Subscriber用于订阅Flowable
rxjava中定义了onext()、onCompleted()、onError()几个方法。
简单用法
//被观察者
Observable<String> observable= Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> e) throws Exception { //此时被观察者发生变化 e.onNext("a"); e.onNext("b"); e.onComplete(); } });
//观察者
Observer<String> observer=new Observer<String>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(String s) { //对变化做出反应 System.out.print(s); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } };
订阅
observable.subscribe(observer);
或者直接这样写
Observable.create(new ObservableOnSubscribe<String>() { @Override public void subscribe(ObservableEmitter<String> e) throws Exception { e.onNext("a"); e.onNext("b"); e.onComplete(); } }).subscribe(new Observer<String>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(String s) { System.out.print(s); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } })
Observable的创建还有其他的方式比如just from等
http://reactivex.io/documentation/operators.html
比如:
Observable<String> observable = Observable.just("Hello", "Hi", "Aloha");
//传递集合的 List<String> list = new ArrayList<String>(); for(int i =0;i<10;i++){ list.add("Hello"+i); } Observable observable = Observable.fromIterable(list);
//设置时间间隔,每隔2秒调用一次onNext()方法Observable<String> observable = Observable.interval(2, TimeUnit.SECONDS);
关于Scheduler
Scheduler 是个调度器,主要用于对线程的控制,Rxjava1.x就已经有自带的几个Scheduler 的相关线程了。
Schedulers.immediate(): 直接在当前线程运行,相当于不指定线程。这是默认的 Scheduler。
Schedulers.newThread(): 总是启用新线程,并在新线程执行操作。
Schedulers.io(): I/O 操作(读写文件、读写数据库、网络信息交互等)所使用的 Scheduler。行为模式和 newThread() 差不多,区别在于 io() 的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下 io() 比 newThread() 更有效率。不要把计算工作放在 io() 中,可以避免创建不必要的线程。
Schedulers.computation(): 计算所使用的 Scheduler。这个计算指的是 CPU 密集型计算,即不会被 I/O 等操作限制性能的操作,例如图形的计算。这个 Scheduler 使用的固定的线程池,大小为 CPU 核数。不要把 I/O 操作放在 computation() 中,否则 I/O 操作的等待时间会浪费 CPU。
另外, Android 还有一个专用的 AndroidSchedulers.mainThread(),它指定的操作将在 Android 主线程运行。
Observable<Integer> obs=Observable.just(1,2,3,4); //在调用 subscribe方法之前先设置线程控制器及具体的线程 obs.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Observer<Integer>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(Integer integer) { } @Override public void onError(Throwable e) { } @Override public void onComplete() { } });
http://gank.io/post/560e15be2dca930e00da1083
- Android MVP +Retrofit+RxJava
- Android Mvp+Rxjava+Retrofit实战
- Android Mvp+RxJava+Retrofit 实战
- Android Retrofit+RxJava+MVP封装
- Android中的RxJava,Retrofit,MVP的使用
- Rxjava + retrofit + dagger2 + mvp搭建Android框架
- [android架构篇]mvp+rxjava+retrofit+eventBus
- [android架构篇]mvp+rxjava+retrofit+eventBus
- android架构篇mvp+rxjava+retrofit+eventBus
- Android MVP+Retrofit+RxJava实践小结
- Android MVP+Retrofit+RxJava实践小结
- Android MVP+RxJava+retrofit 小案例
- Android MVP+Retrofit(封装)+RxJava实例
- Android--MVP+Retrofit+Rxjava的实现
- android+MVP+Retrofit+RxJava做网络请求
- Android MVP+RxJava+Retrofit 的简单模型
- MVP+Dagger2+Retrofit+Rxjava
- Retrofit实践(MVP+RxJava)
- 欢迎使用CSDN-markdown编辑器
- 基于Django1.8.2文档,编写第一个Django应用(1)
- Android Studio中Git的配置及协同开发
- maven依赖的版本管理
- [UOJ#34]多项式乘法(FFT)
- Android MVP +Retrofit+RxJava
- 在Ubuntu上安装、配置和部署Rocket.Chat
- 复旦大学吴立德《数值优化》、《深度学习》和
- ORACLE IP/VIP/SCANIP
- CSS中display:inline;display:block;display:inline-block; 区别
- Swift04-可选类型的声明及使用
- fopen与open的区别
- aop.AopInvocationException: null return value from advice does not match primitive return type for
- 在Java中直接调用js代码