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

优雅地封装使用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等等自己看情况取舍或重写实现。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用RxJava2 + Retrofit2 + OKHttp进行POST请求,可以按照以下步骤进行: 1. 添加依赖 在项目的build.gradle文件中添加以下依赖: ``` dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.2.19' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0' implementation 'com.squareup.okhttp3:okhttp:4.9.1' } ``` 2. 创建Service接口 创建一个接口,用于定义POST请求的方法。例如: ``` public interface ApiService { @POST("login") Observable<LoginResponse> login(@Body LoginRequest request); } ``` 3. 创建Retrofit对象 在Application类或其他初始化类中,创建Retrofit对象: ``` public class MyApp extends Application { private static ApiService apiService; @Override public void onCreate() { super.onCreate(); // 创建OkHttpClient对象 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .build(); // 创建Retrofit对象 Retrofit retrofit = new Retrofit.Builder() .baseUrl("http://example.com/api/") .client(client) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); apiService = retrofit.create(ApiService.class); } public static ApiService getApiService() { return apiService; } } ``` 4. 发起POST请求 在需要发起POST请求的地方,可以使用以下代码: ``` LoginRequest request = new LoginRequest(); request.setUsername("admin"); request.setPassword("123456"); MyApp.getApiService().login(request) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<LoginResponse>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(LoginResponse response) { // 处理响应数据 } @Override public void onError(Throwable e) { // 处理异常 } @Override public void onComplete() { } }); ``` 上述代码中,我们首先创建了一个LoginRequest对象,用于存储要发送的数据。然后调用MyApp.getApiService().login(request)方法,发起POST请求。在这里,我们使用RxJava2的Observable对象,将请求结果封装为一个可观察对象。使用subscribeOn(Schedulers.io())指定在IO线程中进行网络请求,使用observeOn(AndroidSchedulers.mainThread())指定在主线程中处理响应。最后通过subscribe方法订阅请求结果,处理响应数据或异常。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值