关于RxAndroid
关于RxAndroid
背景交代
RxAndroid基于RxJava,又多点特性,比如切换主线程;
响应式编程很火也很好用,但需要一点学习成本
目前Rx系列的教程泛滥,都能够学习Rx的基础和理论知识:
- 不过在看这些教程的时候,总是觉得很多例子太脱离实际,或许是大婶们不屑于用在小地方?
- 对于我来说,需要点直观的实例,才好明白Rx的强大之处。
- 你说他强大,巴拉巴拉一通理论知识,不拿点实例当干货怎么有理有据?
- 在这里就把自己使用过的一些例子做个记录。
实例记录
1.配合Retrofit进行网络请求、加载缓存文件、定时操作、延迟操作...
这几招网上都有,都是常见的用法,不过Rx的优势并不局限于这些用处。
Rx真正的优势在于其灵活性,每个人在使用的过程中都可以总结出自己的一套使用方法。
2.RxBus
比起EventBus,优点是减少一个jar包,减轻apk体积;
3.加载缓存图片
- 之一
Observable.from(mFileNames)
.subscribeOn(Schedulers.io())
//随意切换线程
.observeOn(AndroidSchedulers.mainThread())
//预先做一些处理
.doOnSubscribe(() -> {
for (int i = 0; (i < count) && (first + i < mArrayList.size()); i++) {
if (mArrayList.get(first + i).hasThumbnail) {
mFileNames.add(mArrayList.get(first + i).path);
}
}
})
//操作完成后刷新
.doOnCompleted(this::notifyDataSetChanged)
.map((Func1<String, Object>) s -> FMThumbnailHelper.findThumbnailInCache(mContext, s))
.subscribe(o -> {
});
我觉得Rx一定要搭配lambda,不然复杂了看起来也会显得混乱,配合lambda后,简洁之风扑面而来。
这里主要是doOnSubscribe和doOnCompleted进行预、后处理,再配合lambda,使得代码逻辑清晰,简洁迷人。
- 之二
代码:
//原始代码
Drawable d = null;
if (null != FMThumbnailHelper.getThumbnailCathe())
d = (Drawable) FMThumbnailHelper.getThumbnailCathe().get(name);
if (null != d)
iv.setImageDrawable(d);
// Rx && Lambda
Observable.just(name)
.filter(s -> null != FMThumbnailHelper.getThumbnailCathe())
.map(s -> (Drawable) FMThumbnailHelper.getThumbnailCathe().get(s))
.filter(drawable -> drawable != null)
.subscribe(iv::setImageDrawable);
- 我觉得这个例子很好,原始代码也不复杂,但是给人一种不舒服的感觉,似乎不够优雅?
- Rx + Lambda处理之后,看起来代码量还增大了,但是逻辑变得一清二楚:filter空的—>map为drawable—>filter空的—> setImageDrawable
- 这不是很优雅吗?看着自己都觉得舒心。
4.根据文件类型加载图标
原始代码:
if (file != null && file.isDirectory()) {
iv.setImageResource(R.drawable.file_icon_folder);
} else {
Drawable d = null;
if (null != FMThumbnailHelper.getThumbnailCathe()) {
d = (Drawable) FMThumbnailHelper.getThumbnailCathe()
.get(path);
}
if (d != null) {
iv.setImageDrawable(d);
} else {
Drawable icon = getDefaultIconByCategory(mCategoryIndex);
if (null == icon) {
iv.setImageResource(MediaFile.getIconForPath(path));
} else {
iv.setImageDrawable(icon);
}
}
}
Rx + Lambda:
Observable<Drawable> source = Observable
.concat(ObservableUtil.getDirectory(context, file),
ObservableUtil.getThumbNail(path),
ObservableUtil.getDefault(context, mCategoryIndex),
ObservableUtil.getMedia(context, path))
.first();
source.subscribe(iv::setImageDrawable);
-
原始代码的逻辑看的有点晕,但实际上是要根据类型选择图标,只不过可供选择的渠道有点多;
-
简而言之:按顺序在有序列表中查找唯一答案;
-
在Rx中使用了concat和first()来确保实现此要求,concat确保按顺序查找,first()要求一旦匹配则停止查找行为;
-
Rx优化过后的代码,不是简洁清晰太多了吗?
5.删除文件及其在媒体库中的文件
原始代码:
if (srcFile.isFile()) {
mCurrentSrcFile = srcFile.getAbsolutePath();
if (srcFile.exists()) {
if (!FileUtil.deleteFile(srcFile)) {
handleResult(ERROR);
} else {
updateProgress();
}
}
} else if (srcFile.isDirectory()) {
mHasDirectory = true;
updateProgress();
File[] files = srcFile.listFiles();
if (files != null) {
for (File f : files) {
filePaths.add(f.getAbsolutePath());
deleteFiles(f);
}
}
if (FileUtil.deleteFile(srcFile)) {
filePaths.add(srcFile.getAbsolutePath());
} else {
handleResult(ERROR);
return false;
}
}
if (!mHasDirectory) {
for (String deleteFileName : filePaths) {
FileUtil.deleteFileInDB(mContext, deleteFileName);
}
} else if (!TextUtils.isEmpty(mCurPath)) {
FileUtil.startMediaScan(mContext, mCurPath);
for (String deleteFileName : filePaths) {
FileUtil.deleteFileInDB(mContext, deleteFileName);
}
}
Rx + lambda:
// delete
Observable.just(rootPath)
//flatMap出所子文件(不包括文件夹)
.flatMap(new Func1<File, Observable<File>>() {
@Override
public Observable<File> call(File file) {
return RxUtil.listFiles(file);
}
})
//显示进度
.doOnSubscribe(() -> updateProgress()
.subscribe(new Subscriber<File>() {
@Override
public void onCompleted() {
//删除完子文件后删除剩余的所有空文件夹
deleteEmptyFolder(rootPath);
//刷新进度
updateProgress();
}
@Override
public void onError(Throwable e) {
//处理异常
handleResult(ERROR_DEL_FAIL);
}
@Override
public void onNext(File f) {
mCurrentSrcFile = f.getAbsolutePath();
mTotalOperSize += f.length();
// 删除发射的那一个文件
FileUtil.deleteFile(f);
//删除媒体库中对应的文件
FileUtil.deleteFileInDB(mContext, mCurrentSrcFile);
//刷新进度
updateProgress();
}
});
// RxUtil
public class RxUtil {
public static Observable<File> listFiles(final File f) {
if (f.isDirectory()) {
return Observable.from(f.listFiles()).flatMap(new Func1<File, Observable<File>>() {
@Override
public Observable<File> call(File file) {
return listFiles(file);
}
});
} else {
return Observable.just(f).filter(file -> f.exists());
}
}
}
- 这次的原始代码稍显复杂,看起来有点绕,且烦人,逻辑很杂乱;
- 但我相信你看了下面Rx的代码之后,顿时会感觉神清气爽。
- 这次运用flatMap来一次发射文件夹内的所有文件,抛弃了大量绕人的if else;
- 充分利用Subscriber的onNext、onError和onCompleted处理对应的逻辑,有条有理

浙公网安备 33010602011771号