一、引入
- 七牛云的官方SDK中只有单图上传。如果想要实现多图的上传可能会想到for循环,递归等解决方案.在这里我分享下我用RxJava+回调接口封装的七牛云多图上传工具类,也算是之前看了老多RxJava文章的一个实践吧。如有不妥之处,还请多多指教啦😁
二、先简单说下七牛
我们公司的项目是图片直接由客户端上传的七牛,然后在给我们服务器传七牛的地址。
- 引入依赖 | 1
 | implementation 'com.qiniu:qiniu-android-sdk:7.3.+'
 |  
 
- 七牛的图片上传 | 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | 
 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) {
 
 if(info.isOK()) {
 Log.i("qiniu", "Upload Success");
 } else {
 Log.i("qiniu", "Upload Fail");
 
 }
 Log.i("qiniu", key + ",\r\n " + info + ",\r\n " + res);
 }
 }, null);
 
 
 |  
 
三、在说几个Rxjava的方法哈哈
括号中的内容为在当前项目中的用途
- fromIterable(发送原始数据,图片地址集合) -  可以接收一个 Iterable 容器作为输入,每次发射一个元素 
- flatMap(将图片地址转为七牛云上传成功后的文件名,具体看代码吧) -  FlatMap操作符使用一个指定的函数对原始Observable发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的Observable,然后FlatMap合并这些Observables发射的数据,最后将合并后的结果当做它自己的数据序列发射。 
- compose(切换线程) -  compose()是唯一一个能够从数据流中得到原始Observable的操作符,所以,那些需要对整个数据流产生作用的操作(比如,subscribeOn()和observeOn())需要使用compose()来实现。 
- 为什么不用compose进行变换 -  答:因为compose是操作的整个流,FlatMap是操作的单独的事件。 
四、工具类代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 
 | public class QiNiuUtils {
 private static String token = "一般是找自己服务器要";
 
 
 
 private static UploadManager uploadManager = new UploadManager();
 
 
 
 
 public interface QiNiuCallback {
 
 
 
 
 void onSuccess(List<String> picUrls);
 
 
 
 
 void onError(String msg);
 }
 
 
 
 
 
 
 
 @SuppressLint("CheckResult")
 public static void putImgs(List<String> images, QiNiuCallback qiNiuCallback) {
 
 ArrayList<String> resultImagePath = new ArrayList<>();
 Observable
 
 .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) -> {
 
 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());
 });
 
 }
 }
 
 | 
六、7月30日更新
为了确保图片顺序,将flatMap修改为concatMap。
注意:emitter.onComplete();
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 | 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
 
 .fromIterable(images)
 
 
 .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/