查看原文
其他

rxjava+retrofit+okhttp+mvp 简单实践

2017-07-03 Kimi 终端研发部


前言介绍

一个关于rxjava+retrofit+okhttp+mvp的封装实现,一步一步教会你如何如何使用RROM的结合,适合于初学者。

该篇是来自于Kimi的投稿,Kimi是一个多年经验的老司机,刚进一家公司就要进行代码重构,rxjava+retrofit+okhttp+mvp将会是一个很好的选择。 

Kimi的博客地址:

http://www.itkimi.com/showArticle.jsp?id=7

正文

Rxjava,Retrofit,Okhttp,MVP,这些关键字都是去年比较流行的,随便一个技术论坛或者技术博客,都可以看到,如果你或者他,还对这些关键词感觉到陌生的话,恭喜你,你和我一样了,OUT了,o(∩_∩)o 。

还有,学习新东西一定不要着急,一步一步来,看一遍不明白,那么回过头来看第二遍,第三遍…..看的多了,熟悉了,那么就会用了,如果有上进心的话,可以研究源码,想想具体实现原理等。

水平线~~~~

Rxjava知识,推荐扔物线的博客,地址:http://gank.io/post/560e15be2dca930e00da1083 

我想说的是,这篇博客我看了不下5遍,刚开始很容易弄晕,后来看着看着就明白了。

Retrofit知识,直接看官方文档,地址:

http://square.github.io/retrofit/

Okhttp知识,也直接看官方文档,地址:

http://square.github.io/okhttp/

MVP 相关,这里推荐先看下谷歌的官方demo,地址:https://github.com/googlesamples/android-architecture

以上截图是官方的demo,MVP,MVVM等都在上面,值得参考。

看完官方的在推荐看下这个博客,地址:

http://www.jianshu.com/p/ac51c9b88af3 

或者 直接拿Github上现成的 MVPArms,地址:

https://github.com/JessYanCoding/MVPArms/wiki

好了,我知道的就这么多了~~~~

现在来看下我项目中自己的实践封装,我尽量写详细点,有问题或者觉得不妥的地方都可以给我提意见,互相帮助,才是学习的进步嘛。

先看下项目的配置文件:

红色框圈中的部分都是依赖,这点AS确实很方便,想想如果换成Eclipse的话,该有多麻烦啊。事实上,现在AS已经慢慢的成为主流了,虽然我现在看的是14年的项目,它是EC结构的,汗。

依赖添加完成后,再来看下项目的包结构:


1.net里放的都是网络请求相关,以及封装okhttp下载监听,上传监听的实现。
2.mvp自然就是View,Presenter,Mode了。
3.util 工具类。
4.view 自定义的view。
5.common 相关通用的东西。


一、网络请求的封装:


网络请求主要看ApiServer.java,RetrofitManager.java,StringObserver.java和BaseObserver.java这四个类即可。

1.ApiServer.java :

public interface ApiServer {    
  @GET("{url}")    Observable<String> get(@Path("url") String url,@QueryMap Map<String, String> maps);    
   @FormUrlEncoded    @POST("{url}")    Observable<String> post( @Path("url") String url, @FieldMap Map<String, String> maps);    
   @POST("{url}")    Observable<String> post(  @Path("url") String url,@Body RequestBody body);    @Multipart    @POST("{url}")    Observable<String> uploadFile( @Path("url") String url, @Part("description") RequestBody description,
   @Part MultipartBody.Part file);    
   @Multipart    @POST("{url}")    Observable<String> uploadFile@Path("url") String url, @PartMap Map<String, RequestBody> map);    
@GET    Call<ResponseBody> downloadFile(@Url String fileUrl);   }

Retrofit的写法和官方的没什么区别,唯一的区别就是url没有写死。定义了几个常用的get,post(key-value以及json),上传文件,下载文件等。

2.RetrofitManager.java

private RetrofitManager() {    mRetrofit = new Retrofit.Builder()            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())            //.addConverterFactory(GsonConverterFactory.create())            .addConverterFactory(ScalarsConverterFactory.create())            .baseUrl(Constant.Base_Url)            .client(getOkhttpClient())            .build();    apiServer = mRetrofit.create(ApiServer.class); }
private OkHttpClient getOkhttpClient() {    HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {        @Override        public void log(String message) {            NetLog.d("", message);        }    });    httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);    mOkhttp = new OkHttpClient.Builder()            .addInterceptor(httpLoggingInterceptor)            .addInterceptor(new PublicParamsInterceptor())            .connectTimeout(CONNEC_TIMEOUT, TimeUnit.SECONDS)            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)            .writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)            .retryOnConnectionFailure(false)            .connectionPool(new ConnectionPool())            .build();    
       return mOkhttp;    }
   public static RetrofitManager getInstance() {    
   if (mInstance == null) {        
       synchronized (RetrofitManager.class) {            
       if (mInstance == null) {                mInstance = new RetrofitManager();            }        }    }    return mInstance; }    
    public ApiServer getApiServer() {          
       return apiServer;     }            
       
       //使用方法
       //单利设计模式,因为整个项目中共用同一个网络请求即可。这些天看的14年的项目,想哭的心都有那~~~       mRetrofit = new Retrofit.Builder()      .addCallAdapterFactory(RxJava2CallAdapterFactory.create())            //.addConverterFactory(GsonConverterFactory.create())      .addConverterFactory(ScalarsConverterFactory.create())       .baseUrl(Constant.Base_Url)      .client(getOkhttpClient())       .build();


看到添加了两个converter了吗,其实是这样的,本来想直接封装成BaseBean的,但是发现后台返回的数据根本就没统一,一下data,一下orders的,唯一统一的就一个resultCode字段,“SUCCESS” 代表成功,否则失败。最可气,最可气的是接口文档都没有,接下来这几天又要自己去整理下接口文档了,香菇。

这也是为什么会有StringObserver.java和BaseObserver.java两个类的出现了,可能也有更好的解决办法,这里只能选择String让调用者自己去解析了。

mOkhttp = new OkHttpClient.Builder()    .addInterceptor(httpLoggingInterceptor)    .addInterceptor(new PublicParamsInterceptor())    .connectTimeout(CONNEC_TIMEOUT, TimeUnit.SECONDS)    .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)    .writeTimeout(READ_TIMEOUT, TimeUnit.SECONDS)    .retryOnConnectionFailure(false)    .connectionPool(new ConnectionPool())    .build();

addInterceptor(httpLoggingInterceptor) 添加日志打印的拦截器
addInterceptor(new PublicParamsInterceptor())添加公共参数的拦截器

看下get,post(key—vaule,json),上传,下载

/** * get请求 接口不统一  只能一个一个去解析了 * * @param url * @param params * @param observer */ public void get(String url, Map<String, String> params, Observer observer) {    getApiServer().get(url, params).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer); } /** * post key-value 请求 * * @param url * @param params * @param observer */ public void post(String url, Map<String, String> params, Observer observer) {    getApiServer().post(url, params).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer); } /** * post json请求 * * @param url * @param json * @param observer */ public void json(String url, String json, Observer observer) {    RequestBody body = RequestBody.create(MediaType.parse("application/json;charset=utf-8"), json);    getApiServer().post(url, body).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer); } /** * 上传单个文件 * * @param url * @param file * @param progress */ public void uploadFile(String url, File file, @NonNull final ProgressListener progress, Observer observer) {    OkHttpClient.Builder newBuilder = mOkhttp.newBuilder();    List<Interceptor> networkInterceptors = newBuilder.networkInterceptors();    Interceptor it = new Interceptor() {        @Override        public Response intercept(Chain arg0) throws IOException {            Request request = arg0.request();            Request build = request.newBuilder().method(request.method(), new ProgressRequestBody(request.body(), progress)).build();            return arg0.proceed(build);        }    };    networkInterceptors.add(it);    ApiServer apiServer = mRetrofit.newBuilder().client(newBuilder.build()).build().create(ApiServer.class);    RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"), file);    MultipartBody.Part part = MultipartBody.Part.createFormData("image", file.getName(), body);    RequestBody des = RequestBody.create(MediaType.parse("multipart/form-data"), "des");    apiServer.uploadFile(url, des, part).subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(observer); }    /** * 下载文件 * * @param url * @param listener */ public void downLoadFile(String url, @NonNull final ProgressListener listener, @NonNull final retrofit2.Callback<ResponseBody> call) {    OkHttpClient.Builder newBuilder = mOkhttp.newBuilder();    List<Interceptor> networkInterceptors = newBuilder.networkInterceptors();    Interceptor it = new Interceptor() {        @Override        public Response intercept(Chain arg0) throws IOException {            Response proceed = arg0.proceed(arg0.request());            ProgressResponseBody body = new ProgressResponseBody(proceed.body(), listener);            return proceed.newBuilder().body(body).build();        }    };    networkInterceptors.add(it);    Retrofit build = mRetrofit.newBuilder().client(newBuilder.build()).build();    ApiServer apiServer = build.create(ApiServer.class);    apiServer.downloadFile(url).enqueue(call); }

使用者直接调用即可,可能封装的不是很好,自己也是第一次使用这些框架的,有问题麻烦提出。

3.StringObserver.java

public abstract class StringObserver implements Observer<String> {
   @Override
   public void onSubscribe(Disposable d) {    }
   @Override
   public void onNext(String s) {    
       try {            onSuccess(s);        }catch (Exception e){            e.printStackTrace();            ToastUtils.showMsg("发生错误,请重试!");            onComplete();        }    }
   @Override
   public void onError(Throwable e) {        e.printStackTrace();        onFaild(e);        onComplete();    }
   protected abstract void onSuccess(String json) throws Exception;protected abstract void onFaild(Throwable e); }


4.BaseObserver.java

public abstract class BaseObserver implements Observer<BaseBean>{    
   @Override    public void onSubscribe(Disposable d) {    }    
   @Override    public void onNext(BaseBean baseBean) {        
       try{            
           if(baseBean != null && baseBean.isSuccess()){                onSuccess(baseBean);            }else{                baseBean.showErrorMsg();            }        }catch (Exception e){            e.printStackTrace();            ToastUtils.showMsg("发生错误,请重试!");            onComplete();        }    }    
   
   @Override    public void onError(Throwable e) {        e.printStackTrace();        onFail();        onComplete();    }  
   
   @Override    public void onComplete() {
       }    
       public abstract void onSuccess(BaseBean baseBean);    
   public abstract void onFail(); }

回调的简单封装,如果接口文档规范的话,使用起来会更加方便。

二、MVP:

看过谷歌官方demo的话,会发现有一个contract把view和presenter关联起来,所以这里也遵循了谷歌的做法,每个界面对应了3个类,分别是presenter,constract,task。

这应该是最基本的一个mvp Demo了,面对这么多的接口,刚开始我也无从去下手,但我们应该学会去接收新鲜事物,不断去学习,去进步。

这里强烈推荐:传统MVP用在项目中是真的方便还是累赘?
地址 http://www.jianshu.com/p/ac51c9b88af3

 项目链接地址:

 Github地址:

https://github.com/andmizi/Rxjava-Retrofit-Okhttp-Mvp

博客链接地址:

Kimi的博客地址:

http://www.itkimi.com/showArticle.jsp?id=7

终端研发部提倡 没有做不到的,只有想不到的。

在这里获得的不仅仅是技术! 


让心,在阳光下学会舞蹈

让灵魂,在痛苦中学会微笑

—终端研发部—



如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809   

微信公众号:终端研发部


            

这里学到的不仅仅是技术





您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存