关于RxAndroid

来源:互联网 发布:东莞cnc编程学徒招聘 编辑:程序博客网 时间:2024/05/29 16:11

关于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:

// deleteObservable.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();                    }                });// RxUtilpublic 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处理对应的逻辑,有条有理

未完待续

0 0