我们公司的项目是图片直接由客户端上传的七牛,然后在给我们服务器传七牛的地址。
引入依赖
implementation 'com.qiniu:qiniu-android-sdk:7.3.+' 复制代码
七牛的图片上传
// 吐槽一下: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); 复制代码
fromIterable(发送原始数据,图片地址集合)
可以接收一个 Iterable 容器作为输入,每次发射一个元素
flatMap(将图片地址转为七牛云上传成功后的文件名,具体看代码吧)
FlatMap操作符使用一个指定的函数对原始Observable发射的每一项数据执行变换操作,这个函数返回一个本身也发射数据的Observable,然后FlatMap合并这些Observables发射的数据,最后将合并后的结果当做它自己的数据序列发射。
compose(切换线程)
compose()是唯一一个能够从数据流中得到原始Observable的操作符,所以,那些需要对整个数据流产生作用的操作(比如,subscribeOn()和observeOn())需要使用compose()来实现。
为什么不用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(); } }); } 复制代码
七牛云文档: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/