Android Mvp+Rxjava+Retrofit实战
2016-08-13 10:53
519 查看
Android Mvp+Rxjava+Retrofit实战
目录结构
build.gradle
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.0.0' compile 'com.orhanobut:logger:1.8' compile 'io.reactivex:rxjava:1.1.7' compile 'io.reactivex:rxandroid:1.2.1' compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.google.code.gson:gson:2.7' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' }
Rxjava+Retrofit统一Http的封装
HttpService
Retrofit的配置public interface HttpService { /** * 测量多点之间的直线距离 * * @param waypoints 需要测距的点的经纬度坐标;需传入两个或更多的点。两个点之间用 “; ”进行分割开,单个点的经纬度用“,”分隔开;例如: waypoints=118 * .77147503233,32.054128923368;116.3521416286, 39.965780080447;116 * .28215586757,39.965780080447 * @param ak * @param output * @return */ @FormUrlEncoded @POST("distance?") Observable<BaseHttpResult<List<String>>> getDistance(@Field("waypoints") String waypoints, @Field("ak") String ak, @Field("output") String output); }
HttpUtil
Retrofit和Rxjava进行结合 封装网络请求类public class HttpUtil { /** * 超时时间 */ private static final int DEFAULT_TIMEOUT = 10; /** * retrofit */ private Retrofit retrofit; /** * 接口请求 */ private HttpService httpService; public HttpService getHttpService() { return httpService; } private HttpUtil() { //创建一个OkHttpClient并设置超时时间 OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); //添加迭代器 httpClientBuilder.addInterceptor(new LoggerInterceptor()); retrofit = new Retrofit.Builder() .client(httpClientBuilder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(StaticCode.BASE_URL) .build(); httpService = retrofit.create(HttpService.class); } //在访问HttpUtil时创建单例 private static class SingletonHolder { private static final HttpUtil INSTANCE = new HttpUtil(); } //获取单例 public static HttpUtil getInstance() { return SingletonHolder.INSTANCE; } /** * 组装Observable * * @param observable */ public Observable packageObservable(Observable observable) { return observable.subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } /** * 获取网络数据不转化 * * @param observable */ public Subscription sendHttp(Observable observable, HttpSubscriber listener) { return packageObservable(observable) .subscribe(listener); } /** * 获取网络数据转化 * * @param observable */ public <T> Subscription sendHttpWithMap(Observable observable, HttpSubscriber<T> listener) { return observable.compose(this.<T>applySchedulers()) .subscribe(listener); } /** * Observable 转化 * * @param <T> * @return */ <T> Observable.Transformer<BaseHttpResult<T>, T> applySchedulers() { return new Observable.Transformer<BaseHttpResult<T>, T>() { @Override public Observable<T> call(Observable<BaseHttpResult<T>> baseHttpResultObservable) { return baseHttpResultObservable.map(new HttpFunc<T>()) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } }; } /** * 用来统一处理Http请求到的数据,并将数据解析成对应的Model返回 * * @param <T> Subscriber真正需要的数据类型 */ private class HttpFunc<T> implements Func1<BaseHttpResult<T>, T> { @Override public T call(BaseHttpResult<T> baseHttpResult) { //获取数据失败则抛出异常 会进入到subscriber的onError中 if (!baseHttpResult.getStatus().equals(StaticCode.HTTP_RESPONSE_SUCCESS)) throw new RuntimeException(baseHttpResult.getStatus()); return baseHttpResult.getResults(); } } }
LoggerInterceptor
日志打印和请求头的增加public class LoggerInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request().newBuilder().addHeader("version", "1.0") .addHeader("clientSort", "android").addHeader("Charset", "UTF-8") .build(); printRequestLog(originalRequest); Response response = null; try { //发送网络请求 response = chain.proceed(originalRequest); printResult(response); } catch (SocketTimeoutException e) { //此处不抛异常 连接超时会crash 没有找到其他好的方法 e.printStackTrace(); } return response; } /** * 打印请求日志 * * @param originalRequest * @return * @throws IOException */ private void printRequestLog(Request originalRequest) throws IOException { FormBody.Builder formBuilder = new FormBody.Builder(); String msg = originalRequest.url() + "\n"; RequestBody oidBody = originalRequest.body(); if (oidBody instanceof FormBody) { FormBody formBody = (FormBody) oidBody; for (int i = 0; i < formBody.size(); i++) { String name = URLDecoder.decode(formBody.encodedName(i), "utf-8"); String value = URLDecoder.decode(formBody.encodedValue(i), "utf-8"); if (!TextUtils.isEmpty(value)) { formBuilder.add(name, value); msg += name + " = " + value + "\n"; } } } Logger.i(msg); } /** * 打印返回日志 * * @param response * @throws IOException */ private void printResult(Response response) throws IOException { ResponseBody responseBody = response.body(); BufferedSource source = responseBody.source(); source.request(Long.MAX_VALUE); // Buffer the entire body. Buffer buffer = source.buffer(); Charset UTF8 = Charset.forName("UTF-8"); MediaType contentType = responseBody.contentType(); if (contentType != null) { UTF8 = contentType.charset(UTF8); } String a = buffer.clone().readString(UTF8); Logger.i(a); } }
BaseHttpResult
public class BaseHttpResult<T> { public String status; private T results; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public T getResults() { return results; } public void setResults(T results) { this.results = results; } }
HttpSubscriber
Rxjava的回调public abstract class HttpSubscriber<T> extends Subscriber<T> { /** * 请求标示 */ private int tag; public HttpSubscriber(int tag) { this.tag = tag; } @Override public void onCompleted() { _complete(); } @Override public void onError(Throwable e) { _complete(); onError(e.getMessage(), tag); } @Override public void onNext(T t) { onSuccess(t, tag); } public abstract void onSuccess(T t, int tag); public abstract void onError(String msg, int tag); public abstract void _complete(); }
Mvp的加入
MvpView
public interface MvpView { void showLoadingDialog(); void dismissLoadingDialog(); }
IBasePresenter
public interface IBasePresenter<V extends MvpView> { void subscribe(); void unsubscribe(); }
BasePresenter
对Presenter公共部分进行初始化public abstract class BasePresenter
使用示例
MainActivity
Activity中实现Viewpublic class MainActivity extends AppCompatActivity implements MainContract.IMainView { private MainPre mainPre; private android.widget.TextView getDistance; private android.widget.TextView firstToSecondDistance; private android.widget.TextView secondToThreeDistance; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.secondToThreeDistance = (TextView) findViewById(R.id.second_to_three_distance); this.firstToSecondDistance = (TextView) findViewById(R.id.first_to_second_distance); this.getDistance = (TextView) findViewById(R.id.get_distance); mainPre = new MainPre(this); getDistance.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mainPre.subscribe(); } }); } @Override public void setFirstPointToSecondPointDistance(String distance) { firstToSecondDistance.setText(distance); } @Override public void setSecondPointToThreePointDistance(String distance) { secondToThreeDistance.setText(distance); } @Override public void showLoadingDialog() { //这边可以做Dialog的显示 Logger.e("请求开始"); } @Override public void dismissLoadingDialog() { //这边可以做Dialog的隐藏 Logger.e("请求结束"); } }
MainContract
public class MainContract { /** * Created by huangweizhou on 16/8/10. */ public interface IMainView extends MvpView { /** * 第一个点和第二个点之间的距离 * * @param distance */ void setFirstPointToSecondPointDistance(String distance); /** * 第二个点和第三个点之间的距离 * * @param distance */ void setSecondPointToThreePointDistance(String distance); } }
MainPre
presenter中绑定对应的View和解析的类型public class MainPre extends BasePresenter<MainContract.IMainView, List<String>> { public MainPre(MainContract.IMainView view) { super(view); } @Override public void onSuccess(List<String> strings, int tag) { baseView.setFirstPointToSecondPointDistance(strings.get(0)); baseView.setSecondPointToThreePointDistance(strings.get(1)); } @Override public void onError(String msg, int tag) { Logger.e(msg); } @Override public void subscribe() { sendHttpWithMap(httpService.getDistance("118.77147503233,32.054128923368;\n" + " 116.3521416286,39.965780080447;116.28215586757,39\n" + " .965780080447", "6cyEpstfAo1HSFGPSeshRXa459p3TyT0", "json")); } }
StaticCode
public class StaticCode { /** * Java地址 */ public static final String BASE_URL = "http://api.map.baidu.com/telematics/v3/"; /** * 获取网络数据成功 */ public static final String HTTP_RESPONSE_SUCCESS = "Success"; }
源码地址
Mvp-RxJava-Retrofit相关文章推荐
- Android:这是一份非常详细的MVP+Rxjava2.0+Retrofit2.0相结合举例RecyclerView的实战篇章
- Android详细的登录注册功能MVP+Rxjava2.0+Retrofit2.0相结合的实战篇章
- Rxjava + retrofit + dagger2 + mvp搭建Android框架
- Android MVP+Retrofit+RxJava实践小结
- Android--带你一点点封装项目 MVP+BaseActivity+Retrofit+Dagger+RxJava(二)
- Android RxJava+Retrofit+MVP 入门总结
- Android MVP+Retrofit+RxJava实践小结
- 基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器
- MVP架构下Android的Rxjava与Retrofit 结合
- Android开源实战:使用MVP+Retrofit开发一款文字阅读APP
- Android中的RxJava,Retrofit,MVP的使用
- Android mvp+retrofit+rxjava 编程实践(一)--BaseActivity
- [置顶] 【android进阶篇】MVP+Retrofit+RxJava框架结合
- Android开源实战:使用MVP+Retrofit开发一款文字阅读APP
- Rxjava + retrofit + dagger2 + mvp搭建Android框架
- android架构篇mvp+rxjava+retrofit+eventBus
- Android三大设计模式之一------------------MVP设计模式(包括rxjava+retrofit网络请求框架)
- 浅谈Android MVP设计模式(简单结合RxJava+Retrofit)
- Android_RxJava + Retrofit + MVP雏形
- Android轻松搭建MVP + Retrofit + RxJava(MR篇)