RxJava2+Retrofit2+RxLifecycle3+OkHttp3网络请求封装

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CherryBean/article/details/86223249

入职公司后,公司要求组件化开发,经过讨论后我将网络请求框架单独进行了封装,不过当时框架里将常用的util和ui均放入到了共同的Common包下,导致里面部分代码耦合,后来为了降低耦合性又将Common拆分为了lib_common和lib_ui,但是lib_ui依赖了lib_common,还是导致部分代码耦合,最新一期为了降低组件之间的耦合性,所以单独将lib_common中的网络请求单独拆分,并且我又做了新的封装和完善,总之网络框架经过3次大的改造后,使用已经非常稳定了。

使用步骤

1.在Application类中进行初始化操作

ApiConfig build = new ApiConfig.Builder()
				.setBaseUrl(baseUrl)//BaseUrl,这个地方加入后项目中默认使用该url
               .setInvalidateToken(0)//Token失效码
               .setSucceedCode(200)//成功返回码
               .setFilter("com.mp5a5.quit.broadcastFilter")//失效广播Filter设置
               //.setDefaultTimeout(2000)//响应时间,可以不设置,默认为2000毫秒
               //.setHeads(headMap)//动态添加的header,也可以在其他地方通过ApiConfig.setHeads()设置
               //.setOpenHttps(true)//开启HTTPS验证
               //.setSslSocketConfigure(sslSocketConfigure)//HTTPS认证配置
               .build();
build.init(this);

2.定义接口

public interface UploadApi {

	@Multipart

	@POST("ues/app/upload/pictures")

   Observable postUpload(@Part List partList);
}

3.创建请求实例

public class UploadService {

private final UploadApi mUploadApi;

private UploadService() {
//推荐使用这种,因为BaseUrl已经初始化了
mUploadApi = RetrofitFactory.getInstance().create(UploadApi.class);
}

public static UploadService getInstance() {

return UploadServiceHolder.S_INSTANCE;

}

private static class UploadServiceHolder {

private static final UploadService S_INSTANCE = new UploadService();

}

public Observable uploadPic(List picList) {

return mUploadApi.postUpload(picList);

}

}

4.发送请求

UploadService.getInstance()
                    .uploadPic(t)
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .compose([email protected]())
                    .subscribe(object : BaseObserver<UploadEntity>(this, true) {
                        override fun onSuccess(response: UploadEntity?) {
                            toast(response?.msg!!)
                        }
                    })

5.效果展示
在这里插入图片描述

封装思想

JDK1.8的使用

由于JDK1.8中接口可以有不需要实现的方法,所以我采用了1.8的新特新封装了网络请求返回参数的回调。1.8还有许多新特性,没有升级的同学可以自己查找资料学习一波。

public interface OnBaseResponseListener {

	/**
	
	* 成功
	
	*
	
	* @param response 成功参数
	
	*/

  void onSuccess(R response);

	/**
	
	* 失败
	
	*
	
	* @param response 失败参数
	
	*/

  default void onFailing(R response) {}

	/**
	
	* 错误
	
	*/

  default void onError() {}

}

其中onSuccess()方法是必须实现的,onFailing(R response)和onError()可以不用实现,如果项目中想处理网络请求失败和错误,则需要重写onFailing(R response)和onError()方法,如果用到了封装的loading框和Toast,则需要super.onFailing(response)和super.onError(e),否则则可以不用super。

网络请求返回的Bean

public class BaseResponseEntity implements Serializable {

  private static final long serialVersionUID = 1L;

  public int code;

  public String msg;

  public boolean success() {
    return ApiConfig.getSucceedCode() == code;
  }

  public int getTokenInvalid() {
    return ApiConfig.getInvalidateToken();
  }

}

这个是项目中所有用到网络请求返回bean的父类,其中code是返回码,根据code判断网络请求状态,例如我有一个请求NBA数据的实例,我返回的bean只需要这样写。

public class NBAEntity extends BaseResponseEntity {


    @SerializedName("error_code")
    public int code;
    public String reason;
    public ResultBean result;


    public static class ResultBean {
      public String title;
      }
}

由于我的项目返回的code码这个字段并不是code,所以可以采用起别名的方式,

	@SerializedName("error_code")
    public int code;

这样就可以解决公司返回的code码字段和我封装的字段不相同的问题,当然每个bean都写这段代码显然不是特别友好,所以你可以再封装一个bean继承自BaseResponseEntity,然后给code起别名就可以了,那样项目中的其他的bean只需要继承你自己封装的bean。

扫描二维码关注公众号,回复: 4857262 查看本文章

网络状态的封装类BaseObserver

public abstract class BaseObserver<T extends BaseResponseEntity> implements Observer<T> {


    /**
     * dialog 显示文字
     */
    private String mMsg;
    private CustomProgressDialogUtils progressDialogUtils;
    private Context mContext;
    private boolean mShowLoading = false;

    /**
     * token失效 发送广播标识
     */
    public static final String TOKEN_INVALID_TAG = "token_invalid";
    public static final String QUIT_APP = "quit_app";

    private static final String CONNECT_ERROR = "网络连接失败,请检查网络";
    private static final String CONNECT_TIMEOUT = "连接超时,请稍后再试";
    private static final String BAD_NETWORK = "服务器异常";
    private static final String PARSE_ERROR = "解析服务器响应数据失败";
    private static final String UNKNOWN_ERROR = "未知错误";
    private static final String RESPONSE_RETURN_ERROR = "服务器返回数据失败";

    public BaseObserver() {
    }

    /**
     * 如果传入上下文,那么表示您将开启自定义的进度条
     *
     * @param context 上下文
     */
    public BaseObserver(Context context, boolean isShow) {
        this.mContext = context;
        this.mShowLoading = isShow;
    }

    /**
     * 如果传入上下文,那么表示您将开启自定义的进度条
     *
     * @param context 上下文
     */
    public BaseObserver(Context context, boolean isShow, String msg) {
        this.mContext = context;
        this.mShowLoading = isShow;
        this.mMsg = msg;
    }

    @Override
    public void onSubscribe(Disposable d) {
        onRequestStart();
    }


    @Override
    public void onNext(T response) {
        onRequestEnd();
        if (response.success()) {
            try {
                onSuccess(response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (response.getTokenInvalid() == response.code) {
            //token失效捕捉,发送广播,在项目中接收该动态广播然后做退出登录等一些列操作
            Intent intent = new Intent();
            intent.setAction(ApiConfig.getQuitBroadcastReceiverFilter());
            intent.putExtra(TOKEN_INVALID_TAG, QUIT_APP);
            AppContextUtils.getContext().sendBroadcast(intent);

        } else {
            try {
                onFailing(response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


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

    private void onException(ExceptionReason reason) {
        switch (reason) {
            case CONNECT_ERROR:
                Toast.makeText(AppContextUtils.getContext(), CONNECT_ERROR, Toast.LENGTH_SHORT).show();
                break;

            case CONNECT_TIMEOUT:
                Toast.makeText(AppContextUtils.getContext(), CONNECT_TIMEOUT, Toast.LENGTH_SHORT).show();
                break;

            case BAD_NETWORK:
                Toast.makeText(AppContextUtils.getContext(), BAD_NETWORK, Toast.LENGTH_SHORT).show();
                break;

            case PARSE_ERROR:
                Toast.makeText(AppContextUtils.getContext(), PARSE_ERROR, Toast.LENGTH_SHORT).show();
                break;

            case UNKNOWN_ERROR:
            default:
                Toast.makeText(AppContextUtils.getContext(), UNKNOWN_ERROR, Toast.LENGTH_SHORT).show();
                break;
        }
    }

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

    /**
     * 网络请求成功并返回正确值
     *
     * @param response 返回值
     */
    public abstract void onSuccess(T response);

    /**
     * 网络请求成功但是返回值是错误的
     *
     * @param response 返回值
     */
    public void onFailing(T response) {
        String message = response.msg;
        if (TextUtils.isEmpty(message)) {
            Toast.makeText(AppContextUtils.getContext(), RESPONSE_RETURN_ERROR, Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(AppContextUtils.getContext(), message, Toast.LENGTH_SHORT).show();
        }
    }


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

    /**
     * 网络请求开始
     */
    private void onRequestStart() {
        if (mShowLoading) {
            showProgressDialog();
        }
    }

    /**
     * 网络请求结束
     */
    private void onRequestEnd() {
        closeProgressDialog();
    }

    /**
     * 开启Dialog
     */
    private void showProgressDialog() {
        progressDialogUtils = new CustomProgressDialogUtils();
        if (TextUtils.isEmpty(mMsg)) {
            progressDialogUtils.showProgress(mContext);
        } else {
            progressDialogUtils.showProgress(mContext, mMsg);
        }
    }

    /**
     * 关闭Dialog
     */
    private void closeProgressDialog() {
        if (progressDialogUtils != null) {
            progressDialogUtils.dismissProgress();
        }
    }

}

在onNext(T response)对网络请求成功和失败进行处理,如果网络请求成功并且code返回的是成功的code码,则直接用抽象方法做了处理,public abstract void onSuccess(T response),如果code返回成功但是是token失效的code码,则使用了动态广播将消息发送出去,项目中受到该广播后,可以做退出登录等一系列操作。如果网络请求返回失败,我只做了Toast操作。网络请求错误则是在onErrorr(Throwable e)中做了处理。

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

Retrofit封装RetrofitFactory

public class RetrofitFactory {


    private final Retrofit.Builder retrofit;
    private Retrofit build;

    private RetrofitFactory() {

        // 指定缓存路径,缓存大小100Mb
        File cacheFile = new File(AppContextUtils.getContext().getCacheDir(), "HttpCache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100);

        OkHttpClient.Builder httpClientBuilder = new OkHttpClient().newBuilder()
                .readTimeout(ApiConfig.getDefaultTimeout(), TimeUnit.MILLISECONDS)
                .connectTimeout(ApiConfig.getDefaultTimeout(), TimeUnit.MILLISECONDS)
                .addInterceptor(HttpLoggerInterceptor.getLoggerInterceptor())
                .addInterceptor(new HttpHeaderInterceptor())
                .addNetworkInterceptor(new HttpCacheInterceptor())
                .cache(cache);

        if (ApiConfig.getOpenHttps()) {
            httpClientBuilder.sslSocketFactory(1 == ApiConfig.getSslSocketConfigure().getVerifyType() ?
                    SslSocketFactory.getSSLSocketFactory(ApiConfig.getSslSocketConfigure().getCertificateInputStream()) :
                    SslSocketFactory.getSSLSocketFactory(), new UnSafeTrustManager());
            httpClientBuilder.hostnameVerifier(new UnSafeHostnameVerify());
        }

        OkHttpClient httpClient = httpClientBuilder.build();

        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .serializeNulls()
                .registerTypeAdapterFactory(new NullTypeAdapterFactory())
                .create();

        retrofit = new Retrofit.Builder()
                .client(httpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create());

        if (!TextUtils.isEmpty(ApiConfig.getBaseUrl())) {
            build = retrofit.baseUrl(ApiConfig.getBaseUrl()).build();
        }

    }

    private static class RetrofitFactoryHolder {
        private static final RetrofitFactory INSTANCE = new RetrofitFactory();
    }

    public static final RetrofitFactory getInstance() {
        return RetrofitFactoryHolder.INSTANCE;
    }


    /**
     * 根据Api接口类生成Api实体
     *
     * @param clazz 传入的Api接口类
     * @return Api实体类
     */
    public <T> T create(Class<T> clazz) {
        checkNotNull(build, "BaseUrl not init,you should init first!");
        return build.create(clazz);
    }

    /**
     * 根据Api接口类生成Api实体
     *
     * @param baseUrl baseUrl
     * @param clazz   传入的Api接口类
     * @return Api实体类
     */
    public <T> T create(String baseUrl, Class<T> clazz) {
        return retrofit.baseUrl(baseUrl).build().create(clazz);
    }

    private <T> T checkNotNull(@Nullable T object, String message) {
        if (object == null) {
            throw new NullPointerException(message);
        }
        return object;
    }
}

create()方法之所以有两个,是因为当时项目中涉及到动态切换BaseUrl需求所以才封装了一个两个参数的create方法。

拦截器封装

缓存拦截器

public class HttpCacheInterceptor implements Interceptor {
    @Override
    @EverythingIsNonNull
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        //没网强制从缓存读取
        if (!NetworkUtils.isConnected(AppContextUtils.getContext())) {
            request = request.newBuilder()
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build();
            Log.e("-->", "no network");
        }

        Response originalResponse = chain.proceed(request);

        if (NetworkUtils.isConnected(AppContextUtils.getContext())) {
            //有网的时候读接口上的@Headers里的配置
            String cacheControl = request.cacheControl().toString();
            return originalResponse.newBuilder()
                    .header("Cache-Control", cacheControl)
                    .removeHeader("Pragma")
                    .build();
        } else {
            return originalResponse.newBuilder()
                    .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
                    .removeHeader("Pragma")
                    .build();
        }
    }
}

请求头拦截器

public class HttpHeaderInterceptor implements Interceptor {

    @Override
    @EverythingIsNonNull
    public Response intercept(Chain chain) throws IOException {

        Request originalRequest = chain.request();

        Map<String, String> heads = ApiConfig.getHeads();

        String token = ApiConfig.getToken();

        Request.Builder authorization = originalRequest.newBuilder()
                .header("Content-type", "application/json")
                .header("Authorization", token)
                .addHeader("Connection", "close")
                .addHeader("Accept-Encoding", "identity");

        //动态添加Header
        if (null != heads) {
            heads.forEach(new BiConsumer<String, String>() {
                @Override
                public void accept(String key, String value) {
                    authorization.addHeader(key, value);
                }
            });
        }

        Request build = authorization.build();

        return chain.proceed(build);
    }
}

log拦截器

public class HttpLoggerInterceptor {

    public static HttpLoggingInterceptor getLoggerInterceptor() {
        //日志拦截器
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(message -> {
            Log.e("-->", message.toString());
        });

        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        return interceptor;
    }

}

HTTPS认证

public class SslSocketFactory {

    /**
     * HTTPS单向认证
     *
     * @return
     */
    public static SSLSocketFactory getSSLSocketFactory(InputStream... certificates) {
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance(ApiConfig.getSslSocketConfigure().getCertificateType());
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            keyStore.load(null);
            int index = 0;
            for (InputStream input : certificates) {
                String iAlias = Integer.toString(index++);
                keyStore.setCertificateEntry(iAlias, certificateFactory.generateCertificate(input));
                try {
                    if (null != input) {
                        input.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            SSLContext sslContext = SSLContext.getInstance(ApiConfig.getSslSocketConfigure().getProtocolType());
            TrustManagerFactory managerF = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            managerF.init(keyStore);
            sslContext.init(null, managerF.getTrustManagers(), new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * HTTPS双向认证
     *
     * @return
     */
    public static SSLSocketFactory getSSLSocketFactory() {

        try {
            KeyStore keyStore = KeyStore.getInstance(ApiConfig.getSslSocketConfigure().getKeystoreType());
            KeyStore trustStore = KeyStore.getInstance(ApiConfig.getSslSocketConfigure().getKeystoreType());
            InputStream keyInput = AppContextUtils.getContext().getAssets().open(ApiConfig.getSslSocketConfigure().getClientPriKey());
            InputStream trustInput = AppContextUtils.getContext().getAssets().open(ApiConfig.getSslSocketConfigure().getTrustPubKey());
            keyStore.load(keyInput, ApiConfig.getSslSocketConfigure().getClientBKSPassword().toCharArray());
            trustStore.load(trustInput, ApiConfig.getSslSocketConfigure().getTruststoreBKSPassword().toCharArray());

            try {
                if (null != keyInput) {
                    keyInput.close();
                }
                if (null != keyInput) {
                    trustInput.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            SSLContext sslContext = SSLContext.getInstance(ApiConfig.getSslSocketConfigure().getProtocolType());
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(ApiConfig.getSslSocketConfigure().getCertificateType());
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(ApiConfig.getSslSocketConfigure().getCertificateType());
            trustManagerFactory.init(trustStore);
            keyManagerFactory.init(keyStore, ApiConfig.getSslSocketConfigure().getClientBKSPassword().toCharArray());
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
public class UnSafeHostnameVerify implements HostnameVerifier {
    @SuppressLint("BadHostnameVerifier")
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
}
public class UnSafeTrustManager implements X509TrustManager {
    @SuppressLint("TrustAllX509TrustManager")
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

    }

    @SuppressLint("TrustAllX509TrustManager")
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
}

Gson返回null处理

public class NullTypeAdapterFactory<T> implements TypeAdapterFactory {

    @Override
    @SuppressWarnings("unchecked")
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        Class<T> rawType= (Class<T>) type.getRawType();
        if (rawType!=String.class) {
            return null;
        }
        return (TypeAdapter<T>) new NullAdapter();
    }
}
public class NullAdapter extends TypeAdapter<String> {

    @Override
    public void write(JsonWriter out, String value) throws IOException {
        if (null == value) {
            out.nullValue();
            return;
        }
        out.value(value);
    }

    @Override
    public String read(JsonReader in) throws IOException {
        if (JsonToken.NULL == in.peek()) {
            in.nextNull();
            return "";
        }
        return in.nextString();
    }
}

使用配置类ApiConfig

这个类是对所有初始化参数进行配置的地方,比如返回码code,BaseURL,失效InvalidateToken,请求头Heads,是否开启https认证等的一系配置。采用了建造者模式,就是为了方便开发者链式调用。

public class ApiConfig implements Serializable {

    private static int mInvalidateToken;
    private static String mBaseUrl;
    private static int mDefaultTimeout = 2000;
    private static int mSucceedCode;
    private static String mQuitBroadcastReceiverFilter;
    private static ArrayMap<String, String> mHeads;
    private static String mToken = "";
    private static boolean mOpenHttps;
    private static SslSocketConfigure mSslSocketConfigure;

    private ApiConfig(Builder builder) {
        mInvalidateToken = builder.invalidateToken;
        mBaseUrl = builder.baseUrl;
        mDefaultTimeout = builder.defaultTimeout;
        mSucceedCode = builder.succeedCode;
        mQuitBroadcastReceiverFilter = builder.broadcastFilter;
        mHeads = builder.heads;
        mOpenHttps = builder.openHttps;
        mSslSocketConfigure = builder.sslSocketConfigure;
    }

    public void init(Context appContext) {
        AppContextUtils.init(appContext);
    }

    public static int getInvalidateToken() {
        return mInvalidateToken;
    }

    public static String getBaseUrl() {
        return mBaseUrl;
    }

    public static int getDefaultTimeout() {
        return mDefaultTimeout;
    }

    public static int getSucceedCode() {
        return mSucceedCode;
    }

    public static String getQuitBroadcastReceiverFilter() {
        return mQuitBroadcastReceiverFilter;
    }

    public static ArrayMap<String, String> getHeads() {
        return mHeads;
    }

    public static void setHeads(ArrayMap<String, String> mHeads) {
        ApiConfig.mHeads = mHeads;
    }


    public static String getToken() {
        return mToken;
    }

    public static void setToken(String mToken) {
        ApiConfig.mToken = mToken;
    }

    public static boolean getOpenHttps() {
        return mOpenHttps;
    }


    public static SslSocketConfigure getSslSocketConfigure() {
        return mSslSocketConfigure;
    }

    public static final class Builder  {

        private int invalidateToken;

        private String baseUrl;

        private int defaultTimeout;

        private int succeedCode;

        private String broadcastFilter;

        private ArrayMap<String, String> heads;

        private boolean openHttps = false;

        private SslSocketConfigure sslSocketConfigure;

        public Builder setHeads(ArrayMap<String, String> heads) {
            this.heads = heads;
            return this;
        }

        public Builder setFilter(@NonNull String filter) {
            this.broadcastFilter = filter;
            return this;
        }


        public Builder setSucceedCode(int succeedCode) {
            this.succeedCode = succeedCode;
            return this;
        }

        public Builder setBaseUrl(String mBaseUrl) {
            this.baseUrl = mBaseUrl;
            return this;
        }

        public Builder setInvalidateToken(int invalidateToken) {
            this.invalidateToken = invalidateToken;
            return this;
        }

        public Builder setDefaultTimeout(int defaultTimeout) {
            this.defaultTimeout = defaultTimeout;
            return this;
        }

        public Builder setOpenHttps(boolean open) {
            this.openHttps = open;
            return this;
        }

        public Builder setSslSocketConfigure(SslSocketConfigure sslSocketConfigure) {
            this.sslSocketConfigure = sslSocketConfigure;
            return this;
        }

        public ApiConfig build() {
            return new ApiConfig(this);
        }
    }
}

文件请求上传

采用RxJava进行流的切换操作。

public Single<List<MultipartBody.Part>> uploadMultiPicList(@NonNull List<File> pathList) {

        return Flowable.fromIterable(pathList).concatMap((Function<File, Flowable<MultipartBody.Part>>) f -> {
            Bitmap bitmap = BitmapFactory.decodeFile(f.toString());
            File file = compressBitmapToFile(bitmap, AppContextUtils.getContext());
            Log.e("-->文件大小:", bytesTrans(file.length()) + ",fileSize=" + file.length() / 1024 + "kb");
            RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
            MultipartBody.Part imageBodyPart = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
            return Flowable.just(imageBodyPart);
        }).collect((Callable<List<MultipartBody.Part>>) ArrayList::new, List::add)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

由于好久都没有写文章了,所以可能存在一些问题欢迎大家指正。

代码传送门:https://github.com/Mp5A5/HttpRequest 欢迎大家fork或者star。

猜你喜欢

转载自blog.csdn.net/CherryBean/article/details/86223249