优雅地封装使用rxjava2+retrofit2发送http请求

来源:互联网 发布:淘宝售假被扣24分 编辑:程序博客网 时间:2024/06/14 21:58

优雅地封装使用rxjava2+retrofit2发送http请求

一、需要添加的包

implementation 'io.reactivex.rxjava2:rxjava:2.1.6'implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'implementation 'com.squareup.retrofit2:retrofit:2.3.0'implementation 'com.squareup.retrofit2:converter-gson:2.3.0'implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'implementation 'com.google.code.gson:gson:2.8.2'

二、服务器返回的数据格式封装model
1、这里因为返回的实际有效数据Data可能是不确定的数据类型,所以用泛型,使用时指定具体类型。
2、@SerializedName(value = “Status”, alternate = {“status”}),是在Gson把json数据转换的时候对应key的名称,这里的意思是把json中Status或者status都识别为T data。
3、ResultError是另外一个错误信息实体类。

package cn.syninfo.carwork.model;import com.google.gson.annotations.SerializedName;/** * Created by CHHUANG on 2017/11/2. */public class ResultData<T> {    @SerializedName(value = "Status", alternate = {"status"})    private boolean status;    @SerializedName(value = "Data", alternate = {"data"})    private T data;    @SerializedName(value = "Count", alternate = {"count"})    private Integer count;    @SerializedName(value = "Error", alternate = {"error"})    private ResultError error;    public ResultData(boolean status, T data, Integer count, ResultError error) {        this.status = status;        this.data = data;        this.count = count;        this.error = error;    }    public boolean isStatus() {        return status;    }    public void setStatus(boolean status) {        this.status = status;    }    public T getData() {        return data;    }    public void setData(T data) {        this.data = data;    }    public ResultError getError() {        return error;    }    public void setError(ResultError error) {        this.error = error;    }    public Integer getCount() {        return count;    }    public void setCount(Integer count) {        this.count = count;    }    @Override    public String toString() {        return "ResultData{" +                "status=" + status +                ", data=" + data +                ", count=" + count +                ", error=" + (error==null?error:error.toString()) +                '}';    }}

返回错误信息实体类

package cn.syninfo.carwork.model;import com.google.gson.Gson;import com.google.gson.JsonArray;import com.google.gson.JsonObject;import com.google.gson.annotations.SerializedName;import java.util.List;/** * Created by CHHUANG on 2017/11/2. */public class ResultError {    @SerializedName(value = "Code", alternate = {"code"})    private Integer code;    @SerializedName(value = "Message", alternate = {"message"})    private String message;    @SerializedName(value = "MessageDetail", alternate = {"messageDetail"})    private String messageDetail;    @SerializedName(value = "ModelState", alternate = {"modelState"})    private List<JsonObject> modelState;    public ResultError(Integer code, String message, String messageDetail, List<JsonObject> modelState) {        this.code = code;        this.message = message;        this.messageDetail = messageDetail;        this.modelState = modelState;    }    public Integer getCode() {        return code;    }    public String getMessage() {        return message;    }    public String getMessageDetail() {        return messageDetail;    }    public void setCode(Integer code) {        this.code = code;    }    public void setMessage(String message) {        this.message = message;    }    public void setMessageDetail(String messageDetail) {        this.messageDetail = messageDetail;    }    public List<JsonObject> getModelState() {        return modelState;    }    public void setModelState(List<JsonObject> modelState) {        this.modelState = modelState;    }    @Override    public String toString() {        return "ResultError{" +                "code='" + code + '\'' +                ", message='" + message + '\'' +                ", messageDetail='" + messageDetail + '\'' +                ", modelState=" + (modelState==null?modelState:modelState.toString()) +                '}';    }}

三、封装Retrofit.Builder,同时创建http请求接口

package cn.syninfo.carwork.service;import retrofit2.Retrofit;import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;import retrofit2.converter.gson.GsonConverterFactory;/** * Created by CHHUANG on 2017/11/2. */public class AppRequest {    private AppRequest(){}    private static final String BASE_URL = "http://127.0.0.1:8080/";//这里最后一定要有一个/    private Retrofit retrofit = new Retrofit.Builder()                .addConverterFactory(GsonConverterFactory.create())                //.addCallAdapterFactory(RxJavaCallAdapterFactory.create())//配置rxjava                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())// 针对rxjava2.x                .baseUrl(BASE_URL)                .build();    private AppService service = retrofit.create(AppService.class);    private static AppRequest instance;    public static synchronized AppRequest getInstance(){        if(instance == null)            instance = new AppRequest();        return instance;    }    public AppService getService() {        return service;    }}

http请求接口
1、@POST(“User/Login”)//服务器请求地址
2、Flowable

package cn.syninfo.carwork.service;import cn.syninfo.carwork.model.ResultData;import io.reactivex.Flowable;import io.reactivex.Observable;import retrofit2.http.Field;import retrofit2.http.FormUrlEncoded;import retrofit2.http.POST;/** * Created by CHHUANG on 2017/11/2. */public interface AppService {    /**     * 登录     * //使用@Field模仿表单提交时需要加了@FormUrlEncoded,     * //@Query请求参数。无论是GET或POST的参数都可以用它来实现     * @param username     * @param password     * @return     */    @FormUrlEncoded    @POST("User/Login")//服务器地址    Flowable<ResultData<String>> login(@Field("LoginName") String username, @Field("LoginPwd") String password);}

四、封装rxjava构成compose,一般情况下的请求都可以用。
1、NetWorkUtils.isNetworkConnected(context),这个方法是用来判断是否有网络,放在doOnSubscribe中,会在执行subscribe方法前执行
2、这里要用FlowableTransformer,因为用了rxjava2的Flowable

package cn.syninfo.carwork.service;import android.content.Context;import android.widget.Toast;import org.reactivestreams.Publisher;import org.reactivestreams.Subscription;import cn.syninfo.carwork.R;import cn.syninfo.carwork.utils.NetWorkUtils;import io.reactivex.Flowable;import io.reactivex.FlowableTransformer;import io.reactivex.android.schedulers.AndroidSchedulers;import io.reactivex.functions.Consumer;import io.reactivex.schedulers.Schedulers;/** * Created by CHHUANG on 2017/11/29. */public class ServiceRxSchedulers {    public static <T> FlowableTransformer<T, T> compose(final Context context) {        return new FlowableTransformer<T, T>() {            @Override            public Publisher<T> apply(Flowable<T> upstream) {                return upstream.subscribeOn(Schedulers.io())                        .doOnSubscribe(new Consumer<Subscription>() {                            @Override                            public void accept(Subscription subscription) throws Exception {                                if (!NetWorkUtils.isNetworkConnected(context)) {//没有网络                                    Toast.makeText(context, R.string.bad_network, Toast.LENGTH_SHORT).show();                                }                            }                        }).observeOn(AndroidSchedulers.mainThread());            }        };    }}

五、实现FlowableSubscriber,封装预处理,处理掉可以公共处理的部分,留下ResultData中的data部分给调用端处理,只留下onHandleSuccess方法在new的时候实现它。

package cn.syninfo.carwork.service;import android.content.Context;import android.util.Log;import android.widget.Toast;import com.google.gson.JsonObject;import org.reactivestreams.Subscription;import java.util.List;import cn.syninfo.carwork.model.ResultData;import cn.syninfo.carwork.model.ResultError;import io.reactivex.FlowableSubscriber;/** * Created by CHHUANG on 2017/11/29. */public abstract class ServiceSubscriber<T> implements FlowableSubscriber<ResultData<T>> {    private static final String TAG = "BaseObserver";    private Context mContext;    public ServiceSubscriber(Context context) {        this.mContext = context.getApplicationContext();    }    @Override    public void onSubscribe(Subscription s) {        s.request(2);//这里一定要写,估计一般情况上大于0就可以了    }    @Override    public void onNext(ResultData<T> resultData) {        if (resultData.isStatus()) {            T t = resultData.getData();            onHandleSuccess(t);        } else {            onHandleError(resultData.getError());        }    }    @Override    public void onError(Throwable e) {        Log.e(TAG, "error:" + e.toString());    }    @Override    public void onComplete() {        Log.d(TAG, "onComplete");    }    protected abstract void onHandleSuccess(T t);    protected void onHandleError(ResultError error) {        Toast.makeText(mContext, error.getMessage(), Toast.LENGTH_SHORT).show();        if(error.getCode()==-1){            List<JsonObject> errors = error.getModelState();            if(errors!=null && !errors.isEmpty()){                for (JsonObject json : errors){                    Log.i(TAG, "onHandleError: "+json.getAsString());                }            }        }    }}

六、最后调用
下面代码是在fragment中调用的,parentActivity是在getActivity()方法赋值过的全局变量。

//这里new ServiceSubscriber不能写在subscribe()方法中,不然在android studio中会报错。ServiceSubscriber serviceSubscriber = new ServiceSubscriber<String>(parentActivity) {    @Override    protected void onHandleSuccess(String token) {//登录成功        Log.i(TAG, "onNext: 令牌="+token);        //保存token        //登录成功打开fragment_main        getFragmentManager().beginTransaction().replace(R.id.main_body, new MainFragment()).commit();        parentActivity.setTitle(R.string.app_name);    }};AppRequest.getInstance().getService().login(username, password)    .compose(ServiceRxSchedulers.compose(parentActivity))    .subscribe(serviceSubscriber);

七、当然如果有特殊情况,比如要用到嵌套或者要用doOnNext等等自己看情况取舍或重写实现。

原创粉丝点击