RxJava應用:實現七牛雲多圖上傳

張欽發表於2018-07-28

一、引入

  1. 七牛雲的官方SDK中只有單圖上傳。如果想要實現多圖的上傳可能會想到for迴圈,遞迴等解決方案.在這裡我分享下我用RxJava+回撥介面封裝的七牛雲多圖上傳工具類,也算是之前看了老多RxJava文章的一個實踐吧。如有不妥之處,還請多多指教啦?

二、先簡單說下七牛

我們公司的專案是圖片直接由客戶端上傳的七牛,然後在給我們伺服器傳七牛的地址。

  1. 引入依賴

    implementation 'com.qiniu:qiniu-android-sdk:7.3.+'複製程式碼
  2. 七牛的圖片上傳

    // 吐槽一下:token 官方推薦伺服器生成,可是我司都是客戶端自己搞。。。// UploadManager uploadManager = new UploadManager(config);
    data = <
    File物件、或 檔案路徑、或 位元組陣列>
    String key = <
    指定七牛服務上的檔名,或 null>
    ;
    String token = <
    從服務端SDK獲取>
    ;
    uploadManager.put(data, key, token, new UpCompletionHandler() {
    @Override public void complete(String key, ResponseInfo info, JSONObject res) {
    //res包含hash、key等資訊,具體欄位取決於上傳策略的設定 if(info.isOK()) {
    Log.i("qiniu", "Upload Success");

    } else {
    Log.i("qiniu", "Upload Fail");
    //如果失敗,這裡可以把info資訊上報自己的伺服器,便於後面分析上傳錯誤原因
    } Log.i("qiniu", key + ",\r\n " + info + ",\r\n " + res);

    }
    }, null);
    複製程式碼

三、在說幾個Rxjava的方法哈哈

括號中的內容為在當前專案中的用途

  1. fromIterable(傳送原始資料,圖片地址集合)

    可以接收一個 Iterable 容器作為輸入,每次發射一個元素

  2. flatMap(將圖片地址轉為七牛雲上傳成功後的檔名,具體看程式碼吧)

    FlatMap操作符使用一個指定的函式對原始Observable發射的每一項資料執行變換操作,這個函式返回一個本身也發射資料的Observable,然後FlatMap合併這些Observables發射的資料,最後將合併後的結果當做它自己的資料序列發射。

  3. compose(切換執行緒)

    compose()是唯一一個能夠從資料流中得到原始Observable的操作符,所以,那些需要對整個資料流產生作用的操作(比如,subscribeOn()和observeOn())需要使用compose()來實現。

  4. 為什麼不用compose進行變換

    答:因為compose是操作的整個流,FlatMap是操作的單獨的事件。

四、工具類程式碼

public class QiNiuUtils { 
private static String token = "一般是找自己伺服器要";
/** * 七牛雲SDK */ private static UploadManager uploadManager = new UploadManager();
/** * 回撥介面 */ public interface QiNiuCallback {
/** * 上傳完成 */ void onSuccess(List<
String>
picUrls)
;
/** * 上傳失敗 */ void onError(String msg);

} /** * 上傳圖片到七牛 * * @param images 圖片地址 * @param qiNiuCallback 回撥介面 */ @SuppressLint("CheckResult") public static void putImgs(List<
String>
images, QiNiuCallback qiNiuCallback)
{
// 七牛返回的檔名 ArrayList<
String>
resultImagePath = new ArrayList<
>
();
Observable // 依次傳送list中的資料 .fromIterable(images) // 變換,在這裡上傳圖片 .flatMap((Function<
String, ObservableSource<
String>
>
) path ->
Observable.create(emitter ->
{
String key = UUID.randomUUID().toString() + "." + path.split("\\.")[1];
uploadManager.put(path, key, token, (key1, info, res) ->
{
//res包含hash、key等資訊,具體欄位取決於上傳策略的設定 if (info.isOK()) {
// 上傳成功,傳送這張圖片的檔名 emitter.onNext(key1);

} else {
// 上傳失敗,告辭 emitter.onError(new IOException(info.error));

}
}, null);

}) ) // 執行緒切換 .compose(RxUtil.rxObservableSchedulerHelper()) .subscribe(response ->
{
resultImagePath.add(response);
// 如果全部完成,呼叫成功介面 if (resultImagePath.size() == images.size()) {
qiNiuCallback.onSuccess(resultImagePath);

}
}, throwable ->
{
LogUtils.e(throwable.getMessage());
qiNiuCallback.onError(throwable.getMessage());

});

}
}複製程式碼

五、如何呼叫

// pathResult 是圖片地址集合if (pathResult.size() >
0) {
showProgress();
QiNiuUtils.putImgs(pathResult, new QiNiuUtils.QiNiuCallback() {
@Override public void onSuccess(List<
String>
picUrls)
{
LogUtils.i(picUrls.toString());
showMsg("圖片上傳完成!");
hideProgress();

} @Override public void onError(String msg) {
hideProgress();

}
});

}複製程式碼

六、7月30日更新

為了確保圖片順序,將flatMap修改為concatMap

注意:emitter.onComplete();

public static void putImgs(List<
String>
images, QiNiuCallback qiNiuCallback)
{
String token = Auth.create(Constants.QINIU_AK, Constants.QINIU_SK).uploadToken(Constants.QINIU_SCOPE);
// 七牛返回的檔名 ArrayList<
String>
resultImagePath = new ArrayList<
>
();
Observable // 依次傳送list中的資料 .fromIterable(images) // 變換,在這裡上傳圖片 // 修改為concatMap確保圖片順序 .concatMap((Function<
String, ObservableSource<
String>
>
) path ->
Observable.create((ObservableOnSubscribe<
String>
) emitter ->
{
String key = UUID.randomUUID().toString() + "." + path.split("\\.")[1];
ResponseInfo responseInfo = uploadManager.syncPut(path, key, token, null);
if (responseInfo.isOK()) {
// 上傳成功,傳送這張圖片的檔名 emitter.onNext(key);
emitter.onComplete();

} else {
// 上傳失敗,告辭 emitter.onError(new IOException(responseInfo.error));

}
}).subscribeOn(Schedulers.io()) ) // 執行緒切換 .observeOn(AndroidSchedulers.mainThread()) .subscribe(response ->
{
resultImagePath.add(response);
// 如果全部完成,呼叫成功介面 if (resultImagePath.size() == images.size()) {
qiNiuCallback.onSuccess(resultImagePath);

}
}, throwable ->
{
LogUtils.e(throwable.getMessage());
qiNiuCallback.onError(throwable.getMessage());

});

}複製程式碼

七、相關連結

七牛雲文件:https://developer.qiniu.com/kodo/sdk/1236/android

RxJava的簡單使用:https://www.sdwfqin.com/2016/12/25/rxjava%E7%9A%84%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8/

來源:https://juejin.im/post/5b5bd75cf265da0f6132160a

相關文章