Android OkGo网络请求库 自定义回调支持带泛型的对象

2019-10-22 14:47:48 浏览数 (1)

前言

这里写了两种方式请求接口 (文中用了Java和Kotlin两种语言 没有特殊标示的都是Java)

  • 普通方式
  • Rx方式

建议是用Rx方式

常用调用方式

依赖

名称

引用方式

作用

okhttp-OkGo

compile 'com.lzy.net:okgo:3.0.4'

HTTP请求

fastjson

compile 'com.alibaba:fastjson:1.2.46'

回调转JSON

涉及的实体类

代码语言:javascript复制
public class ResultVo<T> {
	private int code = 0;// 返回是否成功  0成功 1失败  2token不存在
	private String msg = "";// 返回提示信息
	private T obj;// 返回对象或者对象列表

	public ResultVo() {
	}

	public ResultVo(int code, String msg, T list) {
		super();
		this.code = code;
		this.msg = msg;
		this.obj = list;
	}

	public int getCode() {
		return code;
	}

	public void setCode(int code) {
		this.code = code;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public Object getObj() {
		return obj;
	}

	public void setObj(T obj) {
		this.obj = obj;
	}

	@Override
	public String toString() {
		return "ResultVo [code="   code   ", msg="   msg   ", obj="   obj   "]";
	}
}

自定义回调

ZJJsonCallback

代码语言:javascript复制
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.view.Window;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.request.base.Request;
import com.saitongedu.saitongplatformpad.config.ApiConfig;
import com.saitongedu.saitongplatformpad.model.ResultVo;
import com.saitongedu.saitongplatformpad.model.TUserBean;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import okhttp3.Response;
import okhttp3.ResponseBody;

public abstract class ZJJsonCallback<T> extends AbsCallback<T> {

    private ProgressDialog dialog;
    Context mContext = null;
    private Boolean showProgress = true;
    TypeReference<T> type;

    public ZJJsonCallback() {
    }

    public ZJJsonCallback(Activity activity, Boolean showProgress, TypeReference<T> type) {
        this.showProgress = showProgress;
        this.type = type;
        mContext = activity;
        dialog = new ProgressDialog(activity);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setMessage("请求网络中...");
    }

    @Override
    public void onFinish() {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    @Override
    public void onStart(Request<T, ? extends Request> request) {
        super.onStart(request);

        if (dialog != null && !dialog.isShowing()) {
            if (this.showProgress) {
                dialog.show();
            }
        }
        // 主要用于在所有请求之前添加公共的请求头或请求参数
        // 例如登录授权的 token
        Object spusermodel = SPUtils.get(mContext, "spusermodel", "");
        if (!"".equals(spusermodel)) {
            TUserBean user = JSON.parseObject(spusermodel.toString(), TUserBean.class);
            request.params("token", user.getToken());
        }

    }
    
    @Override
    public T convertResponse(Response response) throws Throwable {

        if (response.isSuccessful()) {
            String bodyInfo = "";
            //防止OOM
            try {
                ResponseBody body = response.body();
                bodyInfo = inputStream2String(body.byteStream());
                body.close();

                return JSON.parseObject(bodyInfo, type);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return null;
    }

    public String inputStream2String(InputStream in) throws IOException {
        StringBuffer out = new StringBuffer();
        byte[] b = new byte[4096];
        for (int n; (n = in.read(b)) != -1; ) {
            out.append(new String(b, 0, n));
        }
        return out.toString();
    }
}

ZJStringCallback

代码语言:javascript复制
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.view.Window;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lzy.okgo.callback.AbsCallback;
import com.lzy.okgo.request.base.Request;
import com.saitongedu.saitongplatformpad.model.TUserBean;

import java.io.IOException;
import java.io.InputStream;

import okhttp3.Response;
import okhttp3.ResponseBody;

public abstract class ZJStringCallback extends AbsCallback<String> {

    private ProgressDialog dialog;
    Context mContext = null;
    private Boolean showProgress = true;

    public ZJStringCallback() {
    }

    public ZJStringCallback(Activity activity, Boolean showProgress) {
        this.showProgress = showProgress;
        mContext = activity;
        dialog = new ProgressDialog(activity);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setCanceledOnTouchOutside(false);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setMessage("请求网络中...");
    }

    @Override
    public void onFinish() {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
    }

    @Override
    public void onStart(Request<String, ? extends Request> request) {
        super.onStart(request);

        if (dialog != null && !dialog.isShowing()) {
            if (this.showProgress) {
                dialog.show();
            }
        }
        // 主要用于在所有请求之前添加公共的请求头或请求参数
        // 例如登录授权的 token
        Object spusermodel = SPUtils.get(mContext, "spusermodel", "");
        if (!"".equals(spusermodel)) {
            TUserBean user = JSON.parseObject(spusermodel.toString(), TUserBean.class);
            request.params("token", user.getToken());
        }

    }

    /**
     * 该方法是子线程处理,不能做ui相关的工作
     * 主要作用是解析网络返回的 response 对象,生产onSuccess回调中需要的数据对象
     * 这里的解析工作不同的业务逻辑基本都不一样,所以需要自己实现,以下给出的时模板代码,实际使用根据需要修改
     */
    @Override
    public String convertResponse(Response response) throws Throwable {

        if (response.isSuccessful()) {
            String bodyInfo = "";
            //防止OOM
            try {
                ResponseBody body = response.body();
                bodyInfo = inputStream2String(body.byteStream());
                body.close();
                response.close();
                return bodyInfo;
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return null;
    }

    public String inputStream2String(InputStream in) throws IOException {
        StringBuffer out = new StringBuffer();
        byte[] b = new byte[4096];
        for (int n; (n = in.read(b)) != -1; ) {
            out.append(new String(b, 0, n));
        }
        return out.toString();
    }
}

调用方式

JsonCallback

代码语言:javascript复制
OkGo.post<ResultVo<String>>(ApiConfig.userapi_login)
    .params("loginname", "zhangjian")
    .params("loginpwd", "wangning")
    .params("device", "pad")
    .execute(object : ZJJsonCallback<ResultVo<String>>(
        this,
        true,
        object : TypeReference<ResultVo<String>>(){}
    ) {
        override fun onSuccess(response: Response<ResultVo<String>>) {
            val result = response.body()
            if (result.code == 0) {

            }
        }
    })

StringCallback

代码语言:javascript复制
OkGo.post<String>(ApiConfig.userapi_login)
    .params("loginname", "zhangjian")
    .params("loginpwd", "wangning")
    .params("device", "pad")
    .execute(object : ZJStringCallback(this,true){
        override fun onSuccess(response: Response<String>?) {
            L.i(response!!.body())
        }
    })

Rx方式

依赖

名称

引用方式

作用

Okhttp-OkGo

compile 'com.lzy.net:okgo:3.0.4'compile 'com.lzy.net:okrx2:2.0.2'

HTTP请求

Fastjson

compile 'com.alibaba:fastjson:1.2.46'

回调转JSON

Rxjava

implementation 'io.reactivex.rxjava2:rxjava:2.1.10'

Rx

RxAndroid

implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'

Rx

转换器

代码语言:javascript复制
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lzy.okgo.convert.Converter;

import okhttp3.Response;
import okhttp3.ResponseBody;


public class ZJJsonConvert<T> implements Converter<T> {

    TypeReference<T> type;

    public ZJJsonConvert(TypeReference<T> type) {
        this.type = type;
    }

    @Override
    public T convertResponse(Response response) throws Throwable {
        ResponseBody body = response.body();
        if (body == null) return null;
        String bodyStr = body.string();
        return JSON.parseObject(bodyStr, type);
    }
}

封装接口

代码语言:javascript复制
import com.alibaba.fastjson.TypeReference;
import com.lzy.okgo.OkGo;
import com.lzy.okgo.convert.StringConvert;
import com.lzy.okrx2.adapter.ObservableBody;

import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;


public class ZJUserApi {
    public static Observable<ResultVo<TUserBean>> userapi_login(
        String loginname,
        String loginpwd
    ) {
        Observable<ResultVo<TUserBean>> obs =
            OkGo.<ResultVo<TUserBean>>post(ApiConfig.userapi_login)
            .params("loginname", loginname)
            .params("loginpwd", loginpwd)
            .params("device", "pad")
            .converter(
                new ZJJsonConvert<>(
                    new TypeReference<ResultVo<TUserBean>>() {}
                )
            )
            .adapt(new ObservableBody<ResultVo<TUserBean>>())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread());
        return obs;
    }
}

调用方式

Kotlin

代码语言:javascript复制
ZJUserApi.userapi_login("zhangjian", "123456")
    .subscribe {
        L.i(it.msg)
    }

页面销毁取消请求

要想页面销毁时取消网络请求 就要做如下修改

定义Activity的基类(请忽略onCreate中的方法 只是用来去掉状态栏的背景)

Kotlin

代码语言:javascript复制
open class SBaseActivity : AppCompatActivity() {

    var compositeDisposable: CompositeDisposable? = null

    fun addDisposable(disposable: Disposable) {
        if (null == compositeDisposable) {
            compositeDisposable = CompositeDisposable()
        }
        compositeDisposable?.add(disposable)
    }

    fun dispose(){
        compositeDisposable?.dispose()
    }

    override fun onDestroy() {
        super.onDestroy()
        dispose()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            val window = window
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
            window.statusBarColor = Color.TRANSPARENT
        }
    }
}

调用的方法改成如下(Kotlin)

代码语言:javascript复制
var disposable = ZJUserApi.userapi_login(
    "zhangjian",
    "wangning")
    .subscribe {
        L.i(it.msg)
    }
addDisposable(disposable)

这样页面在销毁时 就会取消请求了

0 人点赞