大飞

大飞 关注TA

挑战一切!

大飞

大飞

关注TA

挑战一切!

  •  世界的顶端
  • 混口饭吃
  • 写了333,609字

最近回复

该文章投稿至Nemo社区   Android  板块 复制链接


rxjava+retrofit2深度封装

发布于 2017/05/24 23:42 2,708浏览 0回复 14,701

rxjava+retrofit2深度封装 

Rxjava+Retrofit网络框架的封装使用如今是非常流行的,看过不少的使用案例,却发现在使用过程中代码量还是比较多的,或者就干脆使用最原始的方法,对于有强迫症的我很难忍受,多一行代码都会让我觉得多余,不愿意去做重复的事情,尽我所能去封装到最少的代码,这就是我。

RxJava:按我的理解就是异步处理机制,当然也可以同步,类似于handle和AsyncTask,好处就同一代码块实现子线程和UI线程的操作,整体风格整洁易读。如果还为对rxjava有所理解,请参考:http://gank.io/post/560e15be2dca930e00da1083;Rxjava不仅仅用于网络方面的请求,比如线程通信,android权限申请等,请参考:http://blog.csdn.net/lzyzsd/article/details/50120801

Retrofit2:一款Square公司开发的现在非常流行的网络框架,其特点是非常简洁,性能好,处理快,目前发现的缺点就是上传大文件OOM,上传大文件建议使用张鸿洋基于okhttp封装的okgo;

废话不多说,进入正题。

第一步:引入Rxjava和Retrofit依赖

compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'io.reactivex:rxjava:1.0.14' compile 'io.reactivex:rxandroid:1.0.1' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'

第二步 获取Retrofit示例

/**
 *
获取Retrofit示例
 * @param
apiUrl
 
* @return
 
*/
private Retrofit.Builder getBuilder(String apiUrl) {
    Retrofit.Builder builder = new Retrofit.Builder();
    builder.client(getOkClient());
    builder.baseUrl(apiUrl);//设置远程地址
    builder.addConverterFactory(new NullOnEmptyConverterFactory());
    builder.addConverterFactory(GsonConverterFactory.create(getGson()));
    builder.addCallAdapterFactory(RxJavaCallAdapterFactory.create());
    return builder;
}

第三步 获取请求服务

 

/**
 *
一般请求服务
 * @param
a
 
* @param <T>
 * @return
 
*/
public T createRequest(Class a) {
    if (httpTask == null) {
        synchronized (HttpUtils.class) {
            if (httpTask == null) {
                httpTask = getBuilder(Api.HOST_URL).build().create(a);
            }
        }
    }
    return (T) httpTask;
}


/**
 *
自定义请求服务
 * @param
a
 
* @param <T>
 * @return
 
*/
public T createRequest(Class a,String baseUrl) {
    if(!customHttpMaps.containsKey(baseUrl)){
        customHttpMaps.put(baseUrl,getBuilder(baseUrl).build().create(a));
    }
    return (T) customHttpMaps.get(baseUrl);
}

最后,整个代码创建在一个类里面,并使用带锁的单例模式获取示例,避免频繁的创建示例,造成没有必要的开销,整个代码如下:


/**
 *
 *
刘宇飞 创建 on 2017/5/15.
 * 描述:
 */

public class HttpUtils {
    private Gson gson;
    private static volatile HttpUtils instance;
    private volatile Object httpTask;
    private static HashMap customHttpMaps = new HashMap<>();
    /**
     *
单例
     * @return
    
*/
   
public static HttpUtils getInstance() {
        if (instance == null) {
            synchronized (HttpUtils.class) {
                if (instance == null) {
                    instance = new HttpUtils();
                }
            }
        }
        return instance;
    }

    /**
     *
获取Retrofit示例
     * @param
apiUrl
    
* @return
    
*/
   
private Retrofit.Builder getBuilder(String apiUrl) {
        Retrofit.Builder builder = new Retrofit.Builder();
        builder.client(getOkClient());
        builder.baseUrl(apiUrl);//设置远程地址
        builder.addConverterFactory(new NullOnEmptyConverterFactory());
        builder.addConverterFactory(GsonConverterFactory.create(getGson()));
        builder.addCallAdapterFactory(RxJavaCallAdapterFactory.create());
        return builder;
    }

    private OkHttpClient getOkClient() {
        //使用OkHttp拦截器可以指定需要的header给每一个Http请求
        OkHttpClient client = new OkHttpClient().newBuilder()
                .readTimeout(20, TimeUnit.SECONDS)
                .connectTimeout(20, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true)
                .writeTimeout(20, TimeUnit.SECONDS)
                .addInterceptor(new LoggingInterceptor())//日志
//            .addInterceptor(new NotEdcodeLoggingInterceptor())//不加密
             //   .addNetworkInterceptor(new RequestHeaderInterceptor())//请求头
                .build();
        return client;
    }

    private Gson getGson() {
        if (gson == null) {
            GsonBuilder builder = new GsonBuilder();
            builder.setLenient();
            builder.setFieldNamingStrategy(new AnnotateNaming());
            builder.serializeNulls();
            gson = builder.create();
        }
        return gson;
    }

    private static class AnnotateNaming implements FieldNamingStrategy {
        @Override
        public String translateName(Field field) {
            ParamNames a = field.getAnnotation(ParamNames.class);
            return a != null ? a.value() : FieldNamingPolicy.IDENTITY.translateName(field);
        }
    }

    /**
     *
一般请求服务
     * @param
a
    
* @param <T>
     * @return
    
*/
   
public T createRequest(Class a) {
        if (httpTask == null) {
            synchronized (HttpUtils.class) {
                if (httpTask == null) {
                    httpTask = getBuilder(Api.HOST_URL).build().create(a);
                }
            }
        }
        return (T) httpTask;
    }


    /**
     *
自定义请求服务
     * @param
a
    
* @param <T>
     * @return
    
*/
   
public T createRequest(Class a,String baseUrl) {
        if(!customHttpMaps.containsKey(baseUrl)){
            customHttpMaps.put(baseUrl,getBuilder(baseUrl).build().create(a));
        }
        return (T) customHttpMaps.get(baseUrl);
    }

    /**
     *
清空重建 防止切换账号 使用共同的请求
     */
   
public void clearHttp(){
        instance=null;
        httpTask=null;
        customHttpMaps.clear();
        gson=null;
    }
}

第四步 与RXjava的结合 关键所在

我采用构建者设计模式,更加灵活的定制需要,首先创建一个抽象工厂,有以下方法:

HttpBuilder setRequsetId(int requsetId);//请求id

HttpBuilder setContext(Context context);//上下文

HttpBuilder setObservable(Observable observable);//观察者

Subscription create(); //创建示例

HttpBuilder  setCallBack(HttpTaskListener listener); //网络监听

最后一步 请求的封装

需要注意的是,请求默认加载进度框,并要对请求进行管理,否则容易出现空指针异常。

private Subscription request() {
         //避免没有必要的请求
        if(CheckNetwork.isNetworkConnected(MyApplication.getContext())){
            CommonUtils.showToast(MyApplication.getContext(),"无网络连接,请检查网络");
            return null;
        }
        if(context!=null){//如果context不为空则显示进度框
            CommonUtils.getInstance().showInfoProgressDialog(context);
        }
        Subscription subscribe = observable
                .subscribeOn(Schedulers.newThread())//请求网络在子线程中
                .observeOn(AndroidSchedulers.mainThread())//回调在主线程中
                .subscribe(new Subscriber>() {
                    @Override
                    public void onCompleted() {
                     CommonUtils.getInstance().hideInfoProgressDialog();
                    }

                    @Override
                    public void onError(Throwable e) {
                         CommonUtils.getInstance().hideInfoProgressDialog();
                        if(listener!=null){
                            listener.onException(requstId);
                        }

                    }

                    @Override
                    public void onNext(BaseRespose baseResponseVo) {
                        CommonUtils.getInstance().hideInfoProgressDialog();
                        if(listener!=null){
                            listener.onSuccess(requstId,baseResponseVo.data);
                        }


                    }
                });
        //activity 或者fragment销毁时 必须销毁所有的请求 不然容易导致空指针
        CommonUtils.getInstance().addSubscription(subscribe);

        return subscribe;
}

 

 

 

这就封装完成了,最后看看如何使用吧,一行代码搞定。

HttpPresenter.getInstance()
        .setRequsetId(10)   //请求id 非必须
        .setContext(mContext)  //上下文 非必须  没有不显示进度框
        .setObservable(httpTask.requestLogin(map))  //必须
        .setCallBack(this)  //回调 非必须
        .create();

更多封装细节,请下载我的github项目:https://github.com/tzz2015/commonLib.git 如有建议,请联系本人,感激不尽。

ost.com{Ȝۡ>


点赞(0)
点了个评