rxjava+retrofit+okhttp+mvp 简单实践

好久没写博客了,汗,平时喜欢看博客,却不喜欢写博客,这样不行的,惭愧!

今年进了一家新公司,老大说了,先熟悉代码,等新的UI出来后,重构。所以,这些天,就一直在熟悉代码并开始项目的最基本框架搭建了。

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 :


    @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:

    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



    @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


    @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

发布了35 篇原创文章 · 获赞 73 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/qq_28268507/article/details/60956377