当前位置 : 主页 > 编程语言 > java >

【Android -- 网络请求】Rxjava + Retrofit 简单封装

来源:互联网 收集:自由互联 发布时间:2022-06-22
前言 ​​Retrofit​​: 是 Square 公司开发的一款正对Android 网络请求的框架。底层基于OkHttp 实现,OkHttp 已经得到了google 官方的认可。RxJava 就是一种用 Java 语言实现的响应式编程,是一个

前言

​​Retrofit​​: 是 Square 公司开发的一款正对Android 网络请求的框架。底层基于OkHttp 实现,OkHttp 已经得到了google 官方的认可。RxJava 就是一种用 Java 语言实现的响应式编程,是一个基于事件订阅的异步执行的一个类库,核心思想是观察者模式。

效果图

【Android -- 网络请求】Rxjava + Retrofit 简单封装_ide

配置

  • build.gradle 中添加相关库:
// 网络请求
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.10'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.google.code.gson:gson:2.8.9'

implementation 'io.github.youth5201314:banner:2.2.2'
//glide
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
  • 添加权限
<!--联网权限-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--检测网络状态权限-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"
tools:ignore="ProtectedPermissions"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"
tools:ignore="ProtectedPermissions"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 从SDCard读取数据权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

封装前简单使用

/**
* 封装之前简单使用
*/
public void normalRequest(View view) {
//第一步:创建Retrofit
Retrofit mRetrofit = new Retrofit.Builder()
.baseUrl(Constants.BASEURL)//添加BaseUrl
.client(MyApplication.mOkHttpClient)//添加OkhttpClient
.addConverterFactory(GsonConverterFactory.create())//添加Gson解析
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())// 添加 rxjava 支持
.build();

//第二步:构建接口
APIService iApiService = mRetrofit.create(APIService.class);

//第三步:构建被观察者对象
Observable<BaseBean<List<BannerBean>>> observable = iApiService.getBanner();

//第四步:订阅
observable.subscribeOn(Schedulers.io())//指定Observable自身在io线程中执行
.observeOn(AndroidSchedulers.mainThread())//指定一个观察者在主线程中国观察这个Observable
.subscribe(new Observer<BaseBean<List<BannerBean>>>() {
@Override
public void onSubscribe(Disposable d) {
Log.e("TAG", "开始之前");
}

@Override
public void onNext(BaseBean<List<BannerBean>> listBaseBean) {
Toast.makeText(MainActivity.this, listBaseBean.getData().toString(), Toast.LENGTH_SHORT).show();
Log.e("TAG", "成功");
}

@Override
public void onError(Throwable e) {
Toast.makeText(MainActivity.this, "失败", Toast.LENGTH_SHORT).show();
Log.e("TAG", "失败");
}

@Override
public void onComplete() {
Log.e("TAG", "结束");
}
});
}

封装

  • 创建 RetrofitClient
  • /**
    * Created on 2021/12/28 14:11
    *
    * @author Kevin
    */
    public class RetrofitClient {
    public static Retrofit mRetrofit;

    /**
    * 为我们的Client配置参数,使用静态语句块来配置
    * 只执行一次,运行一开始就开辟了内存,内存放在全局
    */
    static {
    mRetrofit = new Retrofit.Builder()
    .baseUrl(Constants.BASEURL)//添加BaseUrl
    .client(MyApplication.mOkHttpClient)//添加OkhttpClient
    .addConverterFactory(GsonConverterFactory.create())//添加Gson解析
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())// 添加 rxjava 支持
    .build();
    }

    /**
    * 所有请求都放在一个接口中
    */
    public static APIService createApi() {
    return mRetrofit.create(APIService.class);
    }

    /**
    * 不同请求放不同接口中
    * @param service 指定接口
    */
    public static <T> T createApi(Class<T> service) {
    return mRetrofit.create(service);
    }


    /**
    * @param context 上下文
    * @param observable 被观察者
    * @param listener 回调接口
    * @param requstName 接口名称
    * @param <T> 实体类
    */
    public static <T> void request(Context context, Observable<T> observable,
    final IResponseCallBack<T> listener, String requstName) {
    Constants.requestName = requstName;
    if (!Utils.isConnected(MyApplication.context)) {
    if (listener != null) {
    listener.onFail(new OkHttpException(-1, "网络不可用,请检查网络"));
    }
    return;
    }
    observable.subscribeOn(Schedulers.io())//指定Observable自身在io线程中执行
    .observeOn(AndroidSchedulers.mainThread())//指定一个观察者在主线程中国观察这个Observable
    .subscribe(new CallBackObserver<T>(listener, context));//订阅

    }

    /**
    * 统一下载图片共用
    * @param observable 被观察者
    * @param callback 回调接口
    * @param imgPath 存储地址
    * @param requstName 功能名称
    */
    public static void downImg(Observable<ResponseBody> observable,
    final IResponseByteCallBack callback, final String imgPath, String requstName) {
    Constants.requestName = requstName;
    observable.subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Observer<ResponseBody>() {
    @Override
    public void onSubscribe(Disposable d) {
    }

    @Override
    public void onNext(ResponseBody responseBody) {
    File file = null;
    try {
    InputStream is = responseBody.byteStream();
    int len = 0;
    // 文件夹路径
    String pathUrl =
    Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator
    + "/PJS/";
    File filepath = new File(pathUrl);
    if (!filepath.exists()) {
    filepath.mkdirs();// 创建文件夹
    }
    file = new File(pathUrl, imgPath);

    FileOutputStream fos = new FileOutputStream(file);

    byte[] buf = new byte[2048];
    while ((len = is.read(buf)) != -1) {
    fos.write(buf, 0, len);
    }
    fos.flush();
    fos.close();
    is.close();
    callback.onSuccess(file);
    } catch (final Exception e) {
    callback.onFailure(e.getMessage());
    }
    }

    @Override
    public void onError(Throwable e) {
    callback.onFailure(e.getMessage());
    }

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

    }
    }
  • 初始化 OkHttpClient.java
  • /**
    * Created on 2021/12/28 14:22
    *
    * @author Kevin
    */
    public class MyApplication extends Application {
    public static Context context;
    public static OkHttpClient mOkHttpClient;
    /**
    * 超时时间
    */
    private static final int TIME_OUT = 30;

    @Override
    public void onCreate() {
    super.onCreate();
    context = getApplicationContext();
    initOkHttp();
    }

    private void initOkHttp() {
    //获取缓存路径
    File cacheDir = MyApplication.context.getExternalCacheDir();

    //设置缓存的大小
    int cacheSize = 10 * 1024 * 1024;
    //创建我们Client对象的构建者
    OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
    okHttpBuilder
    //为构建者设置超时时间
    .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
    .readTimeout(TIME_OUT, TimeUnit.SECONDS)
    .writeTimeout(TIME_OUT, TimeUnit.SECONDS)
    websocket轮训间隔(单位:)
    .pingInterval(20, TimeUnit.SECONDS)
    //设置缓存
    .cache(new Cache(cacheDir.getAbsoluteFile(), cacheSize))
    //允许重定向
    .followRedirects(true)
    //设置拦截器
    .addInterceptor(new RequetInterceptor())
    //添加https支持
    .hostnameVerifier(new HostnameVerifier() {
    @Override
    public boolean verify(String s, SSLSession sslSession) {
    return true;
    }
    })
    .sslSocketFactory(HttpsUtils.initSSLSocketFactory(), HttpsUtils.initTrustManager());

    mOkHttpClient = okHttpBuilder.build();

    }
    }
  • 观察者 CallBackObserver
  • /**
    * Created on 2021/12/28 14:05
    *
    * @author Kevin
    */
    public class CallBackObserver<T> implements Observer<T> {
    private IResponseCallBack<T> mListener;
    private Activity activity;

    public CallBackObserver(IResponseCallBack<T> listener, Context context) {
    this.mListener = listener;
    this.activity = (Activity) context;
    }

    @Override
    public void onSubscribe(Disposable d) {
    /**
    * 这里可以 显示加载圈等
    */
    }

    /**
    * 成功
    * @param data
    */
    @Override
    public void onNext(T data) {
    if (mListener != null && !activity.isFinishing()) {
    BaseBean baseBean = (BaseBean) data;
    /**
    * 是否成功
    */
    if (baseBean.isSuccess()) {
    mListener.onSuccess(data);
    }else {
    mListener.onFail(new OkHttpException(baseBean.getErrorCode(), baseBean.getErrorMsg()));
    }
    }

    }

    /**
    * 失败
    * @param e
    */
    @Override
    public void onError(Throwable e) {
    onComplete();
    if (mListener != null && !activity.isFinishing()) {
    /**
    * 处理失败原因
    */
    OkHttpException okHttpException = ExceptionHandle.handleException(e,activity);
    if(okHttpException !=null) {
    mListener.onFail(okHttpException);
    }
    }

    }

    @Override
    public void onComplete() {
    /**
    * 这里可以 关闭加载圈等
    */
    }
    }
  • 回调接口 IResponseCallBack.java
  • /**
    * Created on 2021/12/28 14:09
    * 描述:自定义回调接口
    * @author Kevin
    */
    public interface IResponseCallBack<T> {
    void onSuccess(T data);

    void onFail(OkHttpException failuer);
    }
  • 拦截器 RequetInterceptor.java
  • /**
    * Created on 2021/12/28 14:11
    * 日志拦截器
    * @author Kevin
    */
    public class RequetInterceptor implements Interceptor {
    /**
    * 这个chain里面包含了request和response,所以你要什么都可以从这里拿
    */
    @Override
    public Response intercept(Chain chain) throws IOException {

    /**
    * 可以添加公共头部参数如token
    */
    Request request = chain.request()
    .newBuilder()
    // .header("TOKEN", token)
    // .header("ID", id)
    .build();

    /**
    * 开始时间
    */
    long startTime = System.currentTimeMillis();
    Log.e("TAG","\n"+"requestUrl=" + request.url());
    String method = request.method();

    if ("POST".equals(method)) {
    try {
    JSONObject jsonObject = new JSONObject();
    if (request.body() instanceof FormBody) {
    FormBody body = (FormBody) request.body();
    for (int i = 0; i < body.size(); i++) {
    jsonObject.put(body.encodedName(i), body.encodedValue(i));
    }
    Log.e("TAG","入参JSON= " + jsonObject.toString());
    }
    } catch (JSONException e) {
    e.printStackTrace();
    }
    }

    Response response = chain.proceed(request);
    /**
    * 这里不能直接使用response.body().string()的方式输出日志
    * 因为response.body().string()之后,response中的流会被关闭,程序会报错,我们需要创建出一个新的response给应用层处理
    */
    ResponseBody responseBody = response.peekBody(1024 * 1024);
    Log.e("TAG","出参JSON=" + responseBody.string());
    long endTime = System.currentTimeMillis();
    long duration = endTime - startTime;
    Log.e("TAG","----------" + Constants.requestName + "耗时:" + duration + "毫秒----------");
    return response;
    }
    }
  • 封装后简单使用
  • /**
    * 封装后使用 GET 请求
    */
    public void getData() {
    RetrofitRequest.getBannerApi(context, new IResponseCallBack<BaseBean<List<BannerBean>>>() {
    @Override
    public void onSuccess(BaseBean<List<BannerBean>> data) {
    List<BannerBean> beans = data.getData();
    images.addAll(beans);
    }

    @Override
    public void onFail(OkHttpException failuer) {
    Toast.makeText(MainActivity.this, "失败", Toast.LENGTH_SHORT).show();
    Log.e("TAG", "失败="+failuer.getEmsg());
    }
    });

    }

    项目地址:​

    参考:
    ​​​深入理解Retrofit源码​​

    ​​Retrofit + RxJava + OkHttp 让网络请求变的简单-基础篇​​

    ​​Retrofit + RxJava + OkHttp 让网络请求变的简单-封装篇​​

    ​​Retrofit 官网​​

    ​​优雅的网络请求框架封装过程​​


    【文章转自香港云服务器 http://www.1234xp.com 复制请保留原URL】
    网友评论