android retrofit2.0+rxjava2.0 封装

最近新开了一个新项目,准备用一下retrofit +rxjava 来做网络请求库。查看了一些牛人的博客,借鉴封装了一下自己的网络请求库

参考:http://www.zhimengzhe.com/Androidkaifa/291654.html

https://blog.csdn.net/silenceoo/article/details/75037576

 

封装后的使用:(取消订阅在BaseActivity 中)

     RetrofitUtils.getInstance()
                .createService(ApiService.class).getUserInfo(1)
                .compose(DeafaultTransformer.<BaseBean<UserInfo>>create())
                .subscribe(new DefaultObserver<UserInfo>(this, true) {
                    @Override
                    public void onSuccess(BaseBean<UserInfo> response) {
                        // 访问成功
                    }
                });

 

app 下的 build.gradle 中添加引用库:

    implementation 'io.reactivex.rxjava2:rxjava:2.0.3'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    implementation 'com.squareup.retrofit2:retrofit:2.3.0'
    implementation 'com.google.code.gson:gson:2.6.2'
    implementation 'com.squareup.retrofit2:converter-gson:2.3.0'//转换器,请求结果转换成Model
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'//配合Rxjava 使用
    implementation 'com.squareup.okhttp3:logging-interceptor:3.8.0'//  日志打印工具

例如:

一个获取用户信息的接口: http://wecome.my.book/getUserInfo?versoin=1(假的)

请求用户信息  返回一段Json 串:

{"code": 200, "message": "成功", 
    "data":{
        "name":"小明"
        "sex": "男"
        "age": 18
    }  
}

一般 应用的接口都统一返回的请求信息

所以可以对实体类进行封装:

BaseBen.class

public class BaseBean<T> implements Serializable {
    private static int SUCCESS_CODE = 200;//接口访问成功的code
    private int code;
    private String message;
    private T data;
    /**
     * 是否成功获取到数据
     */
    public boolean isSuccess() {
        return getCode() == SUCCESS_CODE;
    }

    public int getCode() {
        return code;
    }

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

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

}

实体类: UserInfo.class

public class UserInfo {
    private String name;
    private int age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

定义接口类:

public interface ApiService {
    String baseUrl = "http://welcome.my.book/";

    @GET("getUserInfo")
    Observable<BaseBean<UserInfo>> getUserInfo(@Query("version") int version);

}

封装RetrofitUtils ,创建Retrofit以及添加拦截器:

内部使用静态内部类 单利模式

import android.util.Log;

import com.better.skygo.http.interceptor.HttpHeaderInterceptor;
import com.better.skygo.http.interceptor.LogInterceptor;
import com.better.skygo.utils.LogUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitUtils {
    private static RetrofitUtils utils;
    private final long CONNECT_TIME = 10;
    private final long READ_TIME = 10;
    private OkHttpClient mClient;
    private Retrofit mRetrofit;

    private RetrofitUtils() {
        // 使用 com.squareup.okhttp3:logging-interceptor:3.8.0 日志工具
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(String message) {
                try {
                    String text = URLDecoder.decode(message, "utf-8");
                    LogUtils.d(text);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                    LogUtils.d(message);
                }
            }
        });
        // 日志显示的级别 BODY、NONE、BASIC
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        // 初始化 OkHttpClient
        mClient = new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIME, TimeUnit.SECONDS)//连接超时
                .readTimeout(READ_TIME, TimeUnit.SECONDS)//读取超时
                .addInterceptor(new HttpHeaderInterceptor())
                .addInterceptor(interceptor)// 加入日志拦截
//                .addNetworkInterceptor(new HeadInterceptor) //加入head头
//                .cache() 设置缓存
                .build();
// 初始化 Retrofit
        mRetrofit = new Retrofit.Builder()
                .baseUrl(ApiService.baseUrl)
                .client(mClient)
                .addConverterFactory(GsonConverterFactory.create())//添加Gson解析
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//  添加 rxjava 支持
                .build();
    }

    private static class SingletonHolder {
        private static final RetrofitUtils INSTANCE = new RetrofitUtils();
    }

    public static RetrofitUtils getInstance() {
        return SingletonHolder.INSTANCE;
    }
    
    //  创建网络接口 ApiService
    public <T> T createService(Class<T> clazz) {
        return mRetrofit.create(clazz);
    }
}

封装线程转换器:

每一个请求中都会处理判断 code,根据结果 使用 observeOn和subscribeOn来切换线程。RxJava提供了一种解决方案:Transformer(转换器)。所以需要进行封装:

import com.better.skygo.base.BaseBean;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

/**
 * Describe: 设置网络 请求线程 和 结果处理线程
 */
public class DeafaultTransformer<T> implements ObservableTransformer<T, T> {
    @Override
    public ObservableSource<T> apply(Observable<T> upstream) {
        return upstream.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread()).map(new Function<T, T>() {
                    @Override
                    public T apply(T t) throws Exception {
                
                        return t;
                    }
                });
    }

    public static <T> DeafaultTransformer<T> create() {
        return new DeafaultTransformer<>();
    }
}

定义BaseImpl接口:

包含 网络请求加载框,以及retrofit生命周期管理

import io.reactivex.disposables.Disposable;

/**
 * Describe:  接口访问 弹窗 与 rxjava 取消订阅
 */
public interface BaseImpl {
    //加入订阅

    boolean addRxDestroy(Disposable disposable);
    //移除订阅

    void remove(Disposable disposable);

    /**
     * 显示ProgressDialog
     */
    void showProgress(String msg);

    /**
     * 取消ProgressDialog
     */
    void dismissProgress();
}

构造DefaultObserver:

在DefaultObserver中对服务器异常和网络异常进行处理,加载框ProgressDialog和生命周期管理也在此类中完成。

 

import android.text.TextUtils;
import android.util.Log;

import com.better.skygo.base.BaseBean;
import com.better.skygo.utils.ToastUtils;
import com.google.gson.JsonParseException;

import org.json.JSONException;

import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.text.ParseException;

import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;
import retrofit2.HttpException;

import static com.better.skygo.http.DefaultObserver.ExceptionReason.CONNECT_ERROR;
import static com.better.skygo.http.DefaultObserver.ExceptionReason.CONNECT_TIMEOUT;
import static com.better.skygo.http.DefaultObserver.ExceptionReason.PARSE_ERROR;
import static com.better.skygo.http.DefaultObserver.ExceptionReason.UNKNOWN_ERROR;

/**
 * Describe:请求结果处理,是否显示加载框
 */
public abstract class DefaultObserver<T> implements Observer<BaseBean<T>> {
    private BaseImpl mBaseImpl;

    public DefaultObserver(BaseImpl baseImpl) {
        mBaseImpl = baseImpl;
    }

    /**
     * @param isShowLoading 是否显示加载动画
     */
    protected DefaultObserver(BaseImpl baseImpl, boolean isShowLoading) {
        mBaseImpl = baseImpl;
        if (isShowLoading) {
            mBaseImpl.showProgress("正在加载...");
        }
    }

    @Override
    public void onSubscribe(Disposable d) {
        //  在onDestroy中取消订阅
        mBaseImpl.addRxDestroy(d);
    }

    @Override
    public void onNext(BaseBean<T> response) {
        mBaseImpl.dismissProgress();
        if (response.isSuccess()) {
            onSuccess(response);
        } else {
            onFail(response);
        }
    }

    @Override
    public void onError(Throwable e) {
        mBaseImpl.dismissProgress();
        if (e instanceof HttpException) {     //   HTTP错误
            onException(ExceptionReason.BAD_NETWORK);
        } else if (e instanceof ConnectException
                || e instanceof UnknownHostException) {   //   连接错误
            onException(CONNECT_ERROR);
        } else if (e instanceof InterruptedIOException) {   //  连接超时
            onException(CONNECT_TIMEOUT);
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {   //  解析错误
            onException(PARSE_ERROR);
        } else {
            onException(UNKNOWN_ERROR);
        }
    }

    @Override
    public void onComplete() {
    }

    /**
     * 请求成功
     *
     * @param response 服务器返回的数据
     */
    abstract public void onSuccess(BaseBean<T> response);

    /**
     * 服务器返回数据,但响应码不为200
     *
     * @param response 服务器返回的数据
     */
    private void onFail(BaseBean<T> response) {
        String message = response.getReason();
        if (TextUtils.isEmpty(message)) {
            ToastUtils.showShort("返回错误");
        } else {
            ToastUtils.showShort(message);
        }
    }

    /**
     * 请求异常
     *
     * @param reason Exception
     */
    private void onException(ExceptionReason reason) {
        switch (reason) {
            case CONNECT_ERROR:
                ToastUtils.showShort("连接错误");
                break;
            case CONNECT_TIMEOUT:
                ToastUtils.showShort("连接超时");
                break;
            case BAD_NETWORK:
                ToastUtils.showShort("网络问题");
                break;
            case PARSE_ERROR:
                ToastUtils.showShort("解析数据失败");
                break;
            case UNKNOWN_ERROR:
            default:
                ToastUtils.showShort("未知错误");
                break;
        }
    }

    /**
     * 请求网络失败原因
     */
    public enum ExceptionReason {
        /**
         * 解析数据失败
         */
        PARSE_ERROR,
        /**
         * 网络问题
         */
        BAD_NETWORK,
        /**
         * 连接错误
         */
        CONNECT_ERROR,
        /**
         * 连接超时
         */
        CONNECT_TIMEOUT,
        /**
         * 未知错误
         */
        UNKNOWN_ERROR,
    }
}

封装BaseActivity,Fragment与之类似  管理生命周期,以及实现加载框

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.better.skygo.R;
import com.better.skygo.http.BaseImpl;
import com.better.skygo.MyView.MyHttpLodingDialog;
import com.better.skygo.utils.ScreentUtils;

import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;


public class BaseActivity extends AppCompatActivity implements TitleBarBase, BaseImpl {

    private CompositeDisposable disposablesDestroy;// 管理Destroy取消订阅者者

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        disposables2Destroy = new CompositeDisposable();

    }

    @Override
    public void showProgress(String msg) {
        MyHttpLodingDialog.show(BaseActivity.this, false, msg);
    }

    @Override
    public void dismissProgress() {
        MyHttpLodingDialog.cancle();
    }


    @Override
    public boolean addRxDestroy(Disposable disposable) {
        if (disposablesDestroy == null) {
            throw new IllegalStateException(
                    "addUtilDestroy should be called between onCreate and onDestroy");
        }
        disposablesDestroy.add(disposable);
        return true;
    }

    @Override
    public void remove(Disposable disposable) {
        if (disposablesDestroy == null) {
            throw new IllegalStateException("remove should not be called after onDestroy");
        }
        disposablesDestroy.remove(disposable);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (disposablesDestroy == null) {
            throw new IllegalStateException(
                    "onDestroy called multiple times or onCreate not called");
        }
        disposablesDestroy.dispose();
        disposablesDestroy = null;
    }
}
import android.content.Context;
import android.content.DialogInterface;

/**
 * 可以自己定义样式
 */

public class MyHttpLodingDialog {
    private static android.app.ProgressDialog progressDialog;

    public static void show(Context cxt, boolean cancelable, String str) {
        try {
            progressDialog = new android.app.ProgressDialog(cxt);
            progressDialog.setCancelable(cancelable);
            progressDialog.setMessage(str);
            progressDialog.show();
            progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                @Override
                public void onCancel(DialogInterface dialog) {
                    progressDialog.cancel();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void cancle() {
        if (progressDialog == null)
            return;
        if (progressDialog.isShowing())
            progressDialog.cancel();
    }
}

到这里就完成了。

对这块的封装不太理解的,可以自己手写一遍之后,会收获很多。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值