RxHttp
對RxJava2+Retrofit2+OkHttp3的封裝,優(yōu)雅實現(xiàn)接口請求和文件下載
功能簡介
- 網(wǎng)絡請求(RxRequest)
- 支持監(jiān)聽請求聲明周期,如開始結束和網(wǎng)絡錯誤
- 支持多BaseUrl,可針對不同請求重定向
- 支持針對不同請求設置不同緩存策略,如無網(wǎng)強制獲取緩存,有網(wǎng)緩存有效10秒
- 支持添加公共請求參數(shù)
- 支持自定義異常處理和異常提示消息
- 文件下載(RxDownload)
- 支持斷點續(xù)傳
- 支持下載進度回調
- 支持下載速度回調
- 支持下載過程狀態(tài)監(jiān)聽
- 支持在僅保存下載路徑未保存進度時自動恢復斷點續(xù)傳
- 支持自動獲取真實文件名
發(fā)起請求之RxRequest
使用說明
一、初始化
- 新建網(wǎng)絡請求配置類繼承RequestSetting或DefaultRequestSetting,并復寫部分方法。
public class RxHttpRequestSetting extends DefaultRequestSetting {
@NonNull
@Override
public String getBaseUrl() {
return Config.BASE_URL;
}
@Override
public int getSuccessCode() {
return 200;
}
}
- 在Application中初始化并傳入配置類實例
RxHttp.init(this);
RxHttp.initRequest(new RxHttpRequestSetting());
二、定義公共請求頭攔截器
public class PublicHeadersInterceptor implements Interceptor {
private static String TIME = "";
private static String TOKEN = "";
public static void updateTime(String time) {
PublicHeadersInterceptor.TIME = time;
}
public static void updateToken(String token) {
PublicHeadersInterceptor.TOKEN = token;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
request = request.newBuilder()
.header(Constant.PUBLIC_HEADER_TIME_NAME, TIME)
.header(Constant.PUBLIC_HEADER_SIGN_NAME, getSign(request))
.build();
return chain.proceed(request);
}
private String getSign(Request request){
return MD5Coder.encode(request.url().url().toString() + "?token=" + TOKEN);
}
}
三、定義公共參數(shù)攔截器
public class PublicParamsInterceptor implements Interceptor {
private static final String GET = "GET";
private static final String POST = "POST";
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String method = request.method();
if (TextUtils.equals(method, GET)) {
request = addForGet(request);
} else if (TextUtils.equals(method, POST)) {
request = addForPost(request);
}
return chain.proceed(request);
}
private Request addForGet(Request request) {
List<Param> params = getPublicParams();
HttpUrl httpUrl = request.url();
HttpUrl.Builder httpUrlBuilder = httpUrl.newBuilder();
for (int i = 0; i < httpUrl.querySize(); i++) {
String name = httpUrl.queryParameterName(i);
String value = httpUrl.queryParameterValue(i);
params.add(new Param(name, value));
httpUrlBuilder.removeAllQueryParameters(name);
}
JsonObjUtils json = JsonObjUtils.create();
for (Param param : params) {
json.add(param.getKey(), param.getValue());
}
LogUtils.i("PublicParamsInterceptor", "data=" + json.toJson());
httpUrlBuilder.setQueryParameter(Constant.PUBLIC_PARAM_KEY, json.toJson());
return request.newBuilder()
.url(httpUrlBuilder.build())
.build();
}
private Request addForPost(Request request) {
RequestBody requestBody = request.body();
if (requestBody == null) {
return request;
} else if (requestBody instanceof FormBody) {
List<Param> params = getPublicParams();
FormBody formBody = (FormBody) requestBody;
for (int i = 0; i < formBody.size(); i++) {
params.add(new Param(formBody.name(i), formBody.value(i)));
}
JsonObjUtils json = JsonObjUtils.create();
for (Param param : params) {
json.add(param.getKey(), param.getValue());
}
LogUtils.i("PublicParamsInterceptor", "data=" + json.toJson());
FormBody.Builder formBodyBuilder = new FormBody.Builder()
.add(Constant.PUBLIC_PARAM_KEY, json.toJson());
return request.newBuilder()
.post(formBodyBuilder.build())
.build();
} else if (requestBody instanceof MultipartBody) {
return request;
} else {
try {
if (requestBody.contentLength() == 0) {
List<Param> params = getPublicParams();
JsonObjUtils json = JsonObjUtils.create();
for (Param param : params) {
json.add(param.getKey(), param.getValue());
}
LogUtils.i("PublicParamsInterceptor", "data=" + json.toJson());
FormBody.Builder formBodyBuilder = new FormBody.Builder()
.add(Constant.PUBLIC_PARAM_KEY, json.toJson());
return request.newBuilder()
.post(formBodyBuilder.build())
.build();
} else {
return request;
}
} catch (IOException e) {
return request;
}
}
}
private List<Param> getPublicParams() {
List<Param> params = new ArrayList<>();
params.add(new Param(Constant.PUBLIC_PARAM_SYSTEM_KEY, Constant.PUBLIC_PARAM_SYSTEM_VALUE));
params.add(new Param(Constant.PUBLIC_PARAM_VERSION_KEY, String.valueOf(AppInfoUtils.getVersionCode())));
params.add(new Param(Constant.PUBLIC_PARAM_USER_ID_KEY, UserUtils.getInstance().getUserId()));
params.add(new Param(Constant.PUBLIC_PARAM_USER_DEVICE_KEY, DeviceIdUtils.getId()));
params.add(new Param(Constant.PUBLIC_PARAM_JPUSH_DEVICE_KEY, JPushHelper.getId()));
return params;
}
}
四、定義響應體結構
定義ResponseBean< E >繼承BaseResponse< E >,定義成員變量并實現(xiàn)方法。
public class ResponseBean<E> implements BaseResponse<E> {
@SerializedName(value = "code"/*, alternate = {"status"}*/)
private int code;
@SerializedName(value = "data"/*, alternate = {"result"}*/)
private E data;
@SerializedName(value = "msg"/*, alternate = {"message"}*/)
private String msg;
@Override
public int getCode() {
return code;
}
@Override
public void setCode(int code) {
this.code = code;
}
@Override
public E getData() {
return data;
}
@Override
public void setData(E data) {
this.data = data;
}
@Override
public String getMsg() {
return msg;
}
@Override
public void setMsg(String msg) {
this.msg = msg;
}
}
五、定義接口數(shù)據(jù)結構
public class TimeBean extends BaseBean {
private String token;
private String time;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
六、定義Api接口類
- 新建子類繼承自Api
- 定義一個內部類Service聲明請求
- 定義靜態(tài)無參方法返回Api.api(Service.class)創(chuàng)建Api實例
public class FreeApi extends Api {
public static Service api() {
return Api.api(Service.class);
}
public interface Config {
String BASE_URL = Config.HTTP_HOST + Config.HTTP_VERSION;
long HTTP_TIMEOUT = 5000;
}
public interface Code{
int TIME_OUT = 1000; // 請求延遲
int REQUEST_ERROR = 1001; // 請求方式錯誤
int ILLEGAL_PARAMETER = 1002; // 非法參數(shù)
int SUCCESS = 2000; // 獲取信息成功
int SUCCESS_OLD = 104; // 獲取信息成功 老版本的
int SUCCESS_NO_DATA = 2001; // 暫無相關數(shù)據(jù)
int FAILED = 3000; // 獲取信息失敗
int PHONE_EXIST = 3001; // 該手機號已注冊過
int PASSWARD_ERROR = 3002; // 密碼錯誤
int PHONE_ILLEGAL = 3003; // 手機號不合法
int PHONE_NOT_BIND = 3004; // 請綁定手機號
int PHONE_NOT_REGIST = 3005; // 該手機號未注冊
int ACCOUNT_NOT_EXIST = 4001; // 賬號不存在
int ACCOUNT_EXCEPTION = 4002; // 賬號異常,請重新登錄
int ACCOUNT_FROZEN = 4003; // 該賬戶已被凍結,請聯(lián)系管理員
int ACCOUNT_DELETED = 4004; // 該賬戶已被管理員刪除
int ERROR = 5000; // 訪問異常
int ERROR_NET = 5001; // 網(wǎng)絡異常
}
public interface Service {
@GET("public/time")
Observable<ResponseBean<TimeBean>> getTime();
}
}
七、定義請求回調
public interface RequestBackListener<T> {
void onStart();
void onSuccess(int code, T data);
void onFailed(int code, String msg);
void onNoNet();
void onError(Throwable e);
void onFinish();
}
八、封裝BaseRequest基類
封裝簽名的獲取和響應回調的處理邏輯。
在調用正式接口之前,我們可能需要先調用一個獲取時間戳的接口,將時間戳接口返回的時間戳和簽名字段添加到正式接口的公共參數(shù)或請求頭中,才能發(fā)起正式請求。所以在該基類中進行封裝,抽取公共代碼。
如果時間戳接口返回了版本更新字段,需要版本號等判斷請求的執(zhí)行流程,如強制更新且不需要繼續(xù)執(zhí)行正式接口,可在此處自行處理。
public class BaseRequest {
protected static <T> Disposable requestWithSign(@NonNull RequestCallback<T> observable, @NonNull RequestBackListener<T> callback) {
return request(ProjectApi.api().getTime()
.flatMap(new Function<ResponseBean<TimeBean>, ObservableSource<ResponseBean<T>>>() {
@Override
public Observable<ResponseBean<T>> apply(ResponseBean<TimeBean> bean) {
PublicHeadersInterceptor.updateTime(bean.getData().getTime());
PublicHeadersInterceptor.updateToken(bean.getData().getToken());
return observable.request().subscribeOn(Schedulers.io());
}
}), callback);
}
protected static <T> Disposable request(@NonNull Observable<ResponseBean<T>> observable, @NonNull RequestBackListener<T> callback) {
return RxRequest.create(observable)
.listener(new RxRequest.RequestListener() {
@Override
public void onStart() {
callback.onStart();
}
@Override
public void onError(ExceptionHandle handle) {
handle.getException().printStackTrace();
if (handle.getCode() == ExceptionHandle.Code.NET) {
ToastMaker.showShort(R.string.http_no_net);
callback.onNoNet();
callback.onFailed(ProjectApi.Code.ERROR_NET, ResUtils.getString(R.string.http_no_net));
} else {
callback.onError(handle.getException());
callback.onFailed(ProjectApi.Code.ERROR, ResUtils.getString(R.string.http_error));
}
}
@Override
public void onFinish() {
callback.onFinish();
}
})
.request(new RxRequest.ResultCallback<T>() {
@Override
public void onSuccess(int code, T data) {
callback.onSuccess(code, data);
}
@Override
public void onFailed(int code, String msg) {
if (code == ProjectApi.Code.ACCOUNT_NOT_EXIST ||
code == ProjectApi.Code.ACCOUNT_EXCEPTION ||
code == ProjectApi.Code.ACCOUNT_FROZEN ||
code == ProjectApi.Code.ACCOUNT_DELETED) {
ForceOfflineReceiver.send(code, msg);
}
callback.onFailed(code, msg);
}
});
}
protected interface RequestCallback<T> {
Observable<ResponseBean<T>> request();
}
}
九、新建請求類
public class PublicRequest extends BaseRequest {
/**
* 獲取系統(tǒng)時間
*/
public static Disposable getTime(final RequestBackListener<TimeBean> listener) {
return request(ProjectApi.api().getTime(), listener);
}
/**
* 獲取反饋類型
*/
public static Disposable other(final RequestBackListener<OtherBean> listener) {
return requestWithSign(new RequestCallback<OtherAean>() {
@Override
public Observable<ResponseBean<OtherBean>> request() {
return ProjectApi.api().otherApi();
}
}, listener);
}
}
十、發(fā)起請求
你可以在Activity或者Fragment中發(fā)起請求,也可以在你的Presenter層中發(fā)起請求,只需要注意請求生命周期的管理。
使用時分為3步處理:
- 在onCreate方法中(如果是Presenter中使用應該在其綁定到視圖時)調用RxLife.create()方法,該方法會返回一個RxLife實例mRxLife。
- 在onDestroy方法中(如果是Presenter中使用應該在其從視圖解除綁定時)調用mRxLife.destroy()方法,該方法會自動中斷所有未完成的請求,防止內存泄漏。
- 發(fā)起一個請求,并調用mRxLife.add(Disposable)添加至管理隊列。
下面將以MVP模式進行舉例說明。
- 在P層基類中添加RxLife的創(chuàng)建和銷毀,并提供addToRxLife方法。
public abstract class MvpPresenter<V extends MvpView> {
protected Context context;
private V baseView;
private RxLife rxLife;
void onCreate(V baseView) {
this.baseView = baseView;
context = baseView.getContext();
rxLife = RxLife.create();
}
void onDestroy() {
baseView = null;
context = null;
rxLife.destroy();
rxLife = null;
}
public RxLife getRxLife() {
return rxLife;
}
public void addToRxLife(Disposable disposable) {
if (rxLife != null) {
rxLife.add(disposable);
}
}
public V getBaseView() {
return baseView;
}
public boolean isAttachView() {
return baseView != null;
}
public Context getContext() {
return context;
}
}
- 新建P層,發(fā)起請求。
public class OtherPresenter extends MvpPresenter<FeedbackView> {
public void other() {
addToRxLife(PublicRequest.other(new RequestBackListener<OtherBean>() {
@Override
public void onStart() {
showLoading();
}
@Override
public void onSuccess(int code, OtherBean data) {
if (isAttachView()) {
getBaseView().otherSuccess(code, data);
}
}
@Override
public void onFailed(int code, String msg) {
if (isAttachView()) {
getBaseView().otherFail(code, msg);
}
}
@Override
public void onNoNet() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onFinish() {
dismissLoading();
}
}));
}
}
- 新建V層接口,并在Activity或Fragment實現(xiàn)接口回調,進行數(shù)據(jù)展示。
public interface OtherView extends MvpView {
void otherSuccess(int code, OtherBean data);
void otherFail(int code, String msg);
}
API
JsonObjUtils
創(chuàng)建JSONObject對象并生成Json字符串。
RequestBodyUtils
創(chuàng)建RequestBody,針對POST請求。
如圖片上傳接口
/**
* 鍵 值
* img File
* content String
*/
@Multipart
@POST("public/img")
Observable<ResponseBean<UploadImgBean>> uploadImg(@PartMap Map<String, RequestBody> img);
發(fā)起請求如下
public static Disposable uploadImg(String content, File imgFile, final RequestBackListener<UploadImgBean> listener) {
return requestWithSign(new RequestCallback<UploadImgBean>() {
@Override
public Observable<ResponseBean<UploadImgBean>> request() {
Map<String, RequestBody> map = RequestBodyUtils.builder()
.add("content", content)
.add("img", imgFile)
.build();
return ProjectApi.api().uploadImg(map);
}
}, listener);
}
HttpsCompat
主要提供7個靜態(tài)方法,用于實現(xiàn)證書忽略和開啟Android4.4及以下對TLS1.2的支持。
/**
* 忽略證書的驗證,這樣請求就和HTTP一樣,失去了安全保障,不建議使用
*/
public static void ignoreSSLForOkHttp(OkHttpClient.Builder builder)
/**
* 開啟HttpsURLConnection對TLS1.2的支持
*/
public static void enableTls12ForOkHttp(OkHttpClient.Builder builder)
/**
* 忽略證書的驗證,這樣請求就和HTTP一樣,失去了安全保障,不建議使用
* 應在使用HttpsURLConnection之前調用,建議在application中
*/
public static void ignoreSSLForHttpsURLConnection()
/**
* 開啟HttpsURLConnection對TLS1.2的支持
* 應在使用HttpsURLConnection之前調用,建議在application中
*/
public static void enableTls12ForHttpsURLConnection()
/**
* 獲取開啟TLS1.2的SSLSocketFactory
* 建議在android4.4及以下版本調用
*/
public static SSLSocketFactory getEnableTls12SSLSocketFactory()
/**
* 獲取忽略證書的HostnameVerifier
* 與{@link #getIgnoreSSLSocketFactory()}同時配置使用
*/
public static HostnameVerifier getIgnoreHostnameVerifier()
/**
* 獲取忽略證書的SSLSocketFactory
* 與{@link #getIgnoreHostnameVerifier()}同時配置使用
*/
public static SSLSocketFactory getIgnoreSSLSocketFactory()
常見問題
在Android9.0及以上系統(tǒng)HTTP請求無響應
官方資料在框架安全性變更提及,如果應用以 Android 9 或更高版本為目標平臺則默認情況下啟用網(wǎng)絡傳輸層安全協(xié)議 (TLS),即 isCleartextTrafficPermitted() 函數(shù)返回 false。 如果您的應用需要為特定域名啟用明文,您必須在應用的網(wǎng)絡安全性配置中針對這些域名將 cleartextTrafficPermitted 顯式設置為 true。
因此解決辦法有2種:
第一種,啟用HTTP,允許明文傳輸(不建議采用)
- 在資源文件夾res/xml下面創(chuàng)建network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
</network-security-config>
- 在清單文件AndroidManifest.xml的application標簽里面設置networkSecurityConfig屬性引用。
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application
android:networkSecurityConfig="@xml/network_security_config">
</application>
</manifest>
第二種,所有接口采用HTTPS協(xié)議(建議采用)
此方法需確保后臺正確配置,如配置后仍有無法訪問,且提示證書異常,請檢查后臺配置。
HTTPS請求訪問時提示證書異常
該情況一般為后臺未正確配置證書。請檢查后臺配置。
在測試時,我們可以暫時選擇忽略證書,這樣請求就和HTTP一樣,但會失去安全保障,不允許在正式發(fā)布時使用。
可直接使用HttpsCompat工具類。
實現(xiàn)代碼如下:
public static void ignoreSSLForOkHttp(OkHttpClient.Builder builder) {
builder.hostnameVerifier(getIgnoreHostnameVerifier())
.sslSocketFactory(getIgnoreSSLSocketFactory());
}
public static void ignoreSSLForHttpsURLConnection() {
HttpsURLConnection.setDefaultHostnameVerifier(getIgnoreHostnameVerifier());
HttpsURLConnection.setDefaultSSLSocketFactory(getIgnoreSSLSocketFactory());
}
/**
* 獲取忽略證書的HostnameVerifier
* 與{@link #getIgnoreSSLSocketFactory()}同時配置使用
*/
private static HostnameVerifier getIgnoreHostnameVerifier() {
return new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
};
}
/**
* 獲取忽略證書的SSLSocketFactory
* 與{@link #getIgnoreHostnameVerifier()}同時配置使用
*/
private static SSLSocketFactory getIgnoreSSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, getTrustManager(), new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static TrustManager[] getTrustManager() {
return new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
}
HTTPS請求在Android4.4及以下無法訪問
服務器已正確配置SSL證書,且已打開TLS1.1和TLS1.2,但是在Android4.4及以下無法訪問網(wǎng)絡。是因為在Android4.4及以下版本默認不支持TLS1.2,需要開啟對TLS1.2的支持。代碼如下:
public static void enableTls12ForHttpsURLConnection() {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
SSLSocketFactory ssl = getEnableTls12SSLSocketFactory();
if (ssl != null) {
HttpsURLConnection.setDefaultSSLSocketFactory(ssl);
}
}
}
public static void enableTls12ForOkHttp(OkHttpClient.Builder builder) {
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
SSLSocketFactory ssl = HttpsCompat.getEnableTls12SSLSocketFactory();
if (ssl != null) {
builder.sslSocketFactory(ssl);
}
}
}
public static SSLSocketFactory getEnableTls12SSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, null, null);
return new Tls12SocketFactory(sslContext.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static class Tls12SocketFactory extends SSLSocketFactory {
private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"};
private final SSLSocketFactory delegate;
private Tls12SocketFactory(SSLSocketFactory base) {
this.delegate = base;
}
@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return patch(delegate.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return patch(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return patch(delegate.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return patch(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return patch(delegate.createSocket(address, port, localAddress, localPort));
}
private Socket patch(Socket s) {
if (s instanceof SSLSocket) {
((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION);
}
return s;
}
}
Glide在Android4.4及以下圖片加載失敗
原因同上,需要自定義Glide的AppGlideModule,傳入支持TLS1.2的OkHttpClient。
@GlideModule
public class CustomAppGlideModule extends AppGlideModule {
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(getOkHttpClient()));
}
@Override
public boolean isManifestParsingEnabled() {
return false;
}
private static OkHttpClient getOkHttpClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpsCompat.enableTls12ForOkHttp(builder);
return builder.build();
}
}
文件下載之RxDownload
使用方法
初始化
初始化操作可在Application中也可在應用啟動頁中進行
RxHttp.init(this);
// 可選,未配置設置將自動采用DefaultDownloadSetting
RxHttp.initDownload(new DefaultDownloadSetting() {
@Override
public long getTimeout() {
return 60000;
}
});
調用
RxDownload mRxDownload = RxDownload.create(et_url.getText().toString())
.setDownloadListener(new RxDownload.DownloadListener() {
@Override
public void onStarting(DownloadInfo info) {
tv_start.setText("正在開始...");
}
@Override
public void onDownloading(DownloadInfo info) {
tv_start.setText("正在下載");
}
@Override
public void onError(DownloadInfo info, Throwable e) {
tv_start.setText("下載失敗");
}
@Override
public void onStopped(DownloadInfo info) {
tv_start.setText("已停止");
}
@Override
public void onCanceled(DownloadInfo info) {
tv_start.setText("已取消");
pb_1.setProgress(0);
}
@Override
public void onCompletion(DownloadInfo info) {
tv_start.setText("下載成功");
}
})
.setProgressListener(new RxDownload.ProgressListener() {
@Override
public void onProgress(float progress, long downloadLength, long contentLength) {
pb_1.setProgress((int) (progress * 10000));
}
})
.setSpeedListener(new RxDownload.SpeedListener() {
@Override
public void onSpeedChange(float bytePerSecond, String speedFormat) {
tv_start.setText("正在下載(" + speedFormat + ")");
}
});
tv_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRxDownload.start();
}
});
tv_stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRxDownload.stop();
}
});
tv_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mRxDownload.cancel();
}
});
常用類說明
RxHttp
用于初始化和設置
DownloadSetting/DefaultDownloadSetting
RxDownload的設置
-
String getBaseUrl()
指定默認BaseUrl,傳入一個合法的就可以了
-
long getTimeout()
指定超時時間,建議長一點,如60秒
-
long getConnectTimeout()
設置0則取getTimeout(),單位毫秒
-
long getReadTimeout()
設置0則取getTimeout(),單位毫秒
-
long getWriteTimeout()
設置0則取getTimeout(),單位毫秒
-
String getSaveDirPath()
指定默認的下載文件夾路徑
-
DownloadInfo.Mode getDefaultDownloadMode()
獲取保存路徑的文件已存在但未保存下載進度時的默認模式
DownloadInfo
用于保存下載信息,如需斷點續(xù)傳,需要自己保存以下幾個必傳項
-
String url
下載文件的鏈接(必傳項)
-
String saveDirPath
自定義下載文件的保存目錄(斷點續(xù)傳時必傳項)
-
String saveFileName
自定義下載文件的保存文件名,需帶后綴名(斷點續(xù)傳時必傳項)
-
long downloadLength
已下載文件的長度(斷點續(xù)傳時必傳項)
-
long contentLength
下載文件的總長度
-
State state
當前下載狀態(tài)
-
STARTING
正在開始
-
DOWNLOADING
正在下載
-
STOPPED
未開始/已停止
-
ERROR
下載出錯
-
COMPLETION
下載完成
-
-
Mode mode
獲取保存路徑的文件已存在但未保存下載進度時的模式
-
APPEND
追加
-
REPLACE
替換
-
RENAME
重命名
-
-
create(String)
創(chuàng)建一個下載對象,參數(shù)為url
-
create(String, String, String)
創(chuàng)建一個下載對象,參數(shù)為url/保存目錄/文件名
-
create(String, String, String, long, long)
創(chuàng)建一個下載對象,參數(shù)為url/保存目錄/文件名/已下載長度/總長度
RxDownload
-
create(DownloadInfo)
用于新建一個下載任務
-
setDownloadListener(DownloadListener)
設置下載狀態(tài)監(jiān)聽
-
onStarting()
正在開始,正在連接服務器
-
onDownloading()
正在下載
-
onStopped()
已停止,不會刪除已下載部分,支持斷點續(xù)傳
-
onCanceled()
已取消,會刪除已下載的部分文件,再次開始會重新下載
-
onCompletion(DownloadInfo)
下載完成
-
onError(Throwable)
下載出錯
-
-
setProgressListener(ProgressListener)
-
onProgress(float)
下載進度回調(0~1)
-
-
setSpeedListener(SpeedListener)
-
onSpeedChange(float, String)
下載速度回調,兩個值分別為每秒下載比特數(shù)和格式化后速度(如:1.2KB/s,3.24MB/s)
-
-
start()
開始下載/繼續(xù)下載
-
stop()
停止下載,不會刪除已下載部分,支持斷點續(xù)傳
-
cancel()
取消下載,會刪除已下載的部分文件,再次開始會重新下載
UnitFormatUtils
單位格式化工具
-
calculateSpeed(long, float)
計算速度
-
formatSpeedPerSecond(float)
格式化速度(如:1.12MB/s,628KB/s)
-
formatSpeed(float,TimeUnit)
格式化速度(如:1.12MB/s,628KB/s)
-
formatBytesLength(float)
格式化比特值(如:12.1KB,,187.24MB,154GB)
-
formatTimeUnit(TimeUnit)
格式化時間單位(如:秒為s,毫秒為ms)