androidAndroidAndroid

Retrofit+RxJava+OkHttp链式封装

2016-11-12  本文已影响4173人  愚蠢的高小星

最近公司要开始新项目,准备换掉之前的网络框架。正好最近在看Retrofit+RxJava,感觉还是非常好用的,于是准备将网络框架替换为Retrofit+RxJava+OkHttp。
Retrofit+RxJava的优点很明显:可以实现线程之间的快速切换;处理数据简洁易懂,易于进行元素间的变换;可以简单处理大量的嵌套异步回调等。但是使用Retrofit+RxJava+OkHttp完成一次网络请求还是需要写很多代码的,所以肯定是需要再次封装的。这里我根据项目的特点对Retrofit+RxJava+OkHttp进行了封装,优点是调用方便,代码量少,链式结构清晰。当然,本文只是提供了一种封装方式,只有适合自己项目的封装才是最好的封装~

关于Retrofit+RxJava的基本用法,本文不作详细介绍,可以参考
Retrofit官方文档
给 Android 开发者的 RxJava 详解

先来看一下调用的代码:

    private void doHttpRequest() {
        HttpManager.getInstance()
                .with(this)
                .setObservable(RetrofitManager.getService().getExpress("yuantong", "200382770316"))
                .setDataListener(new HttpDataListener<List<Express>>() {
                    @Override
                    public void onNext(List<Express> list) {
                        //这里对返回数据进行处理
                    }
                });
    }

怎么样,是不是很简单┑( ̄Д  ̄)┍ 几行代码就完成了一次网络请求,使用时只需要传递上下文Context、向接口传递的参数以及返回数据的类型,就可以直接对数据进行处理了!

下面来看一下封装的过程和思路:
常见的接口返回数据的格式一般是这个样子的

{
    "status": 200,
    "message": "success",
    "data": {
        //具体的业务数据
     }
}

我们希望的封装是这样的:对status和判断和message的处理进行封装,在调用时,我们只关心请求成功后返回的数据,只需要在请求成功后对返回的对象进行处理,而请求失败或者其他情况全部进行封装,不在调用时处理。

测试使用的是快递100的测试接口:
http://www.kuaidi100.com/query?type=yuantong&postid=200382770316

来看一下代码~首先是build.gradle文件:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'io.reactivex.rxjava2:rxjava:2.0.1'
    compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

    compile 'com.squareup.retrofit2:retrofit:2.0.1'
    compile 'com.squareup.retrofit2:converter-gson:2.0.1'
    compile 'com.squareup.retrofit2:adapter-rxjava2:+'
    compile 'com.google.code.gson:gson:2.2.4'
    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
}

引入了Retrofit、RxJava、RxAndroid、OkHttp等相关库。

然后是Retrofit的管理类:

public class RetrofitManager {

    public static final String url = "http://www.kuaidi100.com/";
    private static final int TIMEOUT = 15;
    private HttpService httpService;
    private volatile static RetrofitManager singleton;
    private boolean debugMode;

    private RetrofitManager() {
        //OkHttp初始化
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(TIMEOUT, TimeUnit.SECONDS);
        //debug模式打印网络请求日志
        if (debugMode){
            HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(logging);
        }

        //Retrofit初始化
        Retrofit retrofit = new Retrofit.Builder()
            .client(builder.build())
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .baseUrl(url)
            .build();
        httpService = retrofit.create(HttpService.class);
    }

    public static RetrofitManager getInstance() {
        if (singleton == null) {
            synchronized (RetrofitManager.class) {
                if (singleton == null) {
                    singleton = new RetrofitManager();
                }
            }
        }
        return singleton;
    }

    public static HttpService getService(){
        return getInstance().httpService;
    }
}

Retrofit本身不具备http标准网络访问基础,所以还是需要依赖OkHttp进行网络访问。在RetrofitManager类中对OkHttp和Retrofit进行了初始化,同时实例化一个HttpService对象。

HttpService:

public interface HttpService {

    @GET("query")
    Observable<ResultModel<List<Express>>> getExpress(@Query("type") String type,
                                                      @Query("postid") String postid);
}

我们知道,RxJava的基本实现是Observable.subscribe(Observer),通过以上代码我们可以创建出一个Observable对象。那么接下来就需要封装出一个Observer。

返回结果的基础类,统一处理status和message

public class ResultModel<T> {

    private String status;//200成功
    private String message;
    private T data;
}

转换类,利用RxJava的map方法,对ResultModel进行处理后转换为业务实体类

public class ResultMap<T> implements Function<ResultModel<T>, T> {

  @Override
  public T apply(ResultModel<T> httpResult) {
    if ("200".equals(httpResult.getStatus())) {
      return httpResult.getData();
    } else {
      throw new RuntimeException("请求失败(code=" + httpResult.getStatus() + ",message=" + httpResult.getMessage() + ")");
    }
  }
}

Observer封装,显示一个ProgressDialog,同时在请求失败时在OnError回调方法中对错误信息进行处理,在请求成功OnNext回调方法中交给调用者处理。

public class HttpObserver<T> implements Observer<T> {

    private HttpDataListener mSubscriberOnNextListener;
    private WeakReference<Context> context;
    private ProgressDialog dialog;

    public HttpObserver(HttpDataListener mSubscriberOnNextListener, Context context) {
        this.mSubscriberOnNextListener = mSubscriberOnNextListener;
        this.context = new WeakReference<>(context);
        initProgressDialog();
    }

    //自定义ProgressDialog提示文字
    public HttpObserver(HttpDataListener mSubscriberOnNextListener, Context context, String message) {
        this.mSubscriberOnNextListener = mSubscriberOnNextListener;
        this.context = new WeakReference<>(context);
        initProgressDialog(message);
    }

    //自定义ProgressDialog
    public HttpObserver(HttpDataListener mSubscriberOnNextListener, Context context, ProgressDialog dialog) {
        this.mSubscriberOnNextListener = mSubscriberOnNextListener;
        this.context = new WeakReference<>(context);
        this.dialog = dialog;
    }

    private void initProgressDialog() {
        Context context = this.context.get();
        if (dialog == null && context != null) {
            dialog = new ProgressDialog(context);
            dialog.setMessage("加载中……");
            dialog.setCancelable(false);
        }
    }

    private void initProgressDialog(String message) {
        Context context = this.context.get();
        if (dialog == null && context != null) {
            dialog = new ProgressDialog(context);
            dialog.setMessage(message);
            dialog.setCancelable(false);
        }
    }

    private void showProgressDialog() {
        Context context = this.context.get();
        if (dialog == null || context == null) return;
        if (!dialog.isShowing()) {
            dialog.show();
        }
    }

    private void dismissProgressDialog() {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    @Override
    public void onSubscribe(Disposable d) {
        showProgressDialog();
    }

    @Override
    public void onComplete() {
        dismissProgressDialog();
    }

    @Override
    public void onError(Throwable e) {
        Context context = this.context.get();
        if (context == null) return;
        if (e instanceof SocketTimeoutException) {
            Toast.makeText(context, "请求超时", Toast.LENGTH_SHORT).show();
        } else if (e instanceof ConnectException) {
            Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
            Log.d("http", "error----------->" + e.toString());
        }
        dismissProgressDialog();
    }

    @Override
    public void onNext(T t) {
        if (mSubscriberOnNextListener != null) {
            mSubscriberOnNextListener.onNext(t);
        }
    }

}

Http请求管理类

public class HttpManager {
  private volatile static HttpManager singleton;
  private WeakReference<Context> context;
  private Observable observable;
  private HttpObserver observer;

  private HttpManager() {

  }

  public static HttpManager getInstance() {
    if (singleton == null) {
      synchronized (HttpManager.class) {
        if (singleton == null) {
          singleton = new HttpManager();
        }
      }
    }
    return singleton;
  }

  public HttpManager with(Context context) {
    this.context = new WeakReference<>(context);
    return singleton;
  }

  public HttpManager setObservable(Observable observable) {
    this.observable = observable.subscribeOn(Schedulers.io())
        .unsubscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .map(new ResultMap());
    return singleton;
  }

  //创建subscriber
  public void setDataListener(HttpDataListener listener) {
    observer = new HttpObserver(listener, context.get());
    observable.subscribe(observer);
  }

  //创建subscriber 自定义ProgressDialog的文字
  public void setDataListener(HttpDataListener listener, String message) {
    observable.subscribe(new HttpObserver(listener, context.get(), message));
  }

  //创建subscriber 自定义ProgressDialog
  public void setDataListener(HttpDataListener listener, ProgressDialog dialog) {
    observable.subscribe(new HttpObserver(listener, context.get(), dialog));
  }

}

以上,Retrofit+RxJava+OkHttp的封装就完成了。再来回顾一下Http请求的调用:

public class MainActivity extends Activity {

    private TextView data;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        data = (TextView) findViewById(R.id.data);
        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doHttpRequest();
            }
        });
    }

    private void doHttpRequest() {
        HttpManager.getInstance()
            .with(this)
            .setObservable(RetrofitManager.getService().getExpress("yuantong", "200382770316"))
            .setDataListener(new HttpDataListener<List<Express>>() {
                @Override
                public void onNext(List<Express> list) {
                    //这里对返回数据进行处理
                    String result = "";
                    for (int i = 0; i < list.size(); i++){
                        result = result + list.get(i).toString();
                    }
                    data.setText(result);
                }
            });
    }
}

源码下载
https://github.com/GITbiubiubiu/RetrofitDemo

上一篇 下一篇

猜你喜欢

热点阅读