美文网首页
RxJava线程切换的问题

RxJava线程切换的问题

作者: ztzt123 | 来源:发表于2018-02-26 16:31 被阅读0次

专业版在前几个版本一直存在一个问题,就是在首页切换Tab的时候每次都会转圈圈,我们已经使用了Retrofit缓存,正常来说读取缓存数据应该很快。转圈圈给我们的感觉是读取缓存很慢,我们开始怀疑Retrofit读取缓存的问题。我们需找到了原因其实是RxJava切换线程的问题,请求缓存从io线程切换回主线程需要等待一定的时间。看一段我们的测试代码。

    addSubscription(movieBoardUsecase.requestMainBoard(refresh)
            .subscribe(boardTop -> {
                time2 = (Formatter.getCurrentMillis() - time);
                Log.e("timeretrofit", "" + time2);
            }, throwable -> {

            }));

    time3 = Formatter.getCurrentMillis();
    addSubscription(movieBoardUsecase.requestMainBoard(refresh)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(boardTop -> {
                Log.e("timeRXthread", "" + (Formatter.getCurrentMillis() - time3 - time2));
                getView().setData(boardTop);
            }, throwable -> {
            }));

第一段我们不切换线程,直接在主线程请求缓存内的数据,打出发出请求再到获取到数据的时间。

第二段我们正常的切换线程请求缓存,然后减去上面在主线程请求缓存的时间,就获取到切换线程所需要的时间。

我们在页面状态由加载状态变成展示状态的时间。

09-07 22:17:49.176 10745-10745/com.sankuai.moviepro E/timeretrofit: 4
09-07 22:17:49.206 10745-10745/com.sankuai.moviepro E/timeRXthread: 26
09-07 22:17:49.207 10745-10745/com.sankuai.moviepro E/status: 35

上面是在模拟器上运行的时间,可能感觉时间很短,模拟器运行速度较快,参考价值不大,但已经能看出切换线程占用了大部分的耗时。我们换用真机,才能说明问题。

09-08 10:24:42.539 26994-26994/com.sankuai.moviepro E/timeretrofit: 7
09-08 10:24:42.639 26994-26994/com.sankuai.moviepro E/timeRXthread: 91
09-08 10:24:42.644 26994-26994/com.sankuai.moviepro E/status: 112

09-08 10:25:25.676 26994-26994/com.sankuai.moviepro E/timeretrofit: 13
09-08 10:25:25.777 26994-26994/com.sankuai.moviepro E/timeRXthread: 88
09-08 10:25:25.779 26994-26994/com.sankuai.moviepro E/status: 116

09-08 10:25:51.392 26994-26994/com.sankuai.moviepro E/timeretrofit: 28
09-08 10:25:51.609 26994-26994/com.sankuai.moviepro E/timeRXthread: 189
09-08 10:25:51.611 26994-26994/com.sankuai.moviepro E/status: 247

三组数据整体时间不是很稳定,但我们已经可以清楚地看出耗时的并不是Retrofit读取缓存的过程,大部分时间都消耗在RxJava切换线程上。

既然我们已经找到了问题想想解决办法吧。我们可以直接想到的有两种方法,但行不行得通要去试试。

1.在请求之前判断是否存在Http缓存。
2.自己增加一层缓存,优先使用内存缓存,避开retrofit发请求。

第一种方法,我们要在发请求之前知道是否存在Http缓存,http缓存的位置是我们自己指定的,专业版的缓存目录是在应用目录下的cache/responses,下面有好多文件,文件名都是经过加密的,都是.0和.1的文件还有一个journal文件,关于这些文件查了一些资料,okhttp缓存浅析

.0的文件里面是header

.1文件里面是返回的具体内容,即json数据

journal文件里面保存的是每一条reponse记录状态。包括读取,删除,写入等动作。

文件名的加密方式是MD5,可以参考okHttp的Cache。

public static FilterInputStream getFromCache(String url) throws Exception {
    File cacheDirectory = CacheUtils.getCacheDir(MovieProApplication.getContext(), "responses");
    DiskLruCache cache = DiskLruCache.create(FileSystem.SYSTEM, cacheDirectory,
            201105, 2, 10 * 1024 * 1024);
    cache.flush();
    String key = Util.md5Hex(url);
    final DiskLruCache.Snapshot snapshot;
    try {
        snapshot = cache.get(key);
        if (snapshot == null) {
            return null;
        }
    } catch (IOException e) {
        return null;
    }
    okio.Source source = snapshot.getSource(1) ;
    BufferedSource metadata = Okio.buffer(source);
    FilterInputStream bodyIn = new FilterInputStream(metadata.inputStream()) {
        @Override
        public void close() throws IOException {
            snapshot.close();
            super.close();
        }
    };
    return bodyIn ;
}

但是弄了半天我们有一个关键的问题,就是匹配缓存使用的是URL,但是我们在Presenter或者Fragment中并不能获取到URL,要修改的话,改动将会很大,所以这一种方法失败。

第二种是我们自己写内存缓存,还是存在问题,我们要把页面所有的数据缓存起来,使用一个Map,问题就是用什么作为获取缓存的匹配原则呢,正常也应该是通过URL,但是URL的方式行不通,我们只能拿到的是Observable,也无从匹配啊。后来我们重新思考了一下问题,我们当初是为了解决转圈圈的问问题,转圈圈的问题是从loaddata开始,在setData的是后结束。我们只需要避开这个过程,也就不会出现转圈圈的问题,但这只是一个比较差的解法,我们只缓存setData的数据,如果loaddata的时候数据不为空我们直接调用setData,但这样,如果页面有其他数据的话我们setData直接使用缓存,页面展示出来,但其他的请求数据还没有获取到,这样展示出来也会有问题,对于其他的请求我们只能自己写缓存,这样确实不是一个好的解决方法,更好的解决方法还在寻找。

相关文章

  • RxJava线程切换的问题

    专业版在前几个版本一直存在一个问题,就是在首页切换Tab的时候每次都会转圈圈,我们已经使用了Retrofit缓存,...

  • RxJava源码分析-线程切换

    RxJava源码分析-线程切换 接着上篇分析,本篇我们来揭开RxJava线程切换的神秘面试,先上一段代码 这段代码...

  • RxJava的线程切换

    RxJava 线程切换 前言 在上篇文章对RxJava 的工作流程进行的简单的分析,今天来分享一下线程切换的流程。...

  • Rxjava2 操作符原理(2)

    Rxjava2 基本用法(1) Rxjava2 操作符原理(2) Rxjava2 线程切换(3) Rxjava2 ...

  • Rxjava2 线程切换(3)

    Rxjava2 基本用法(1) Rxjava2 操作符原理(2) Rxjava2 线程切换(3) Rxjava2 ...

  • Rxjava2 基本用法(1)

    Rxjava2 基本用法(1) Rxjava2 操作符原理(2) Rxjava2 线程切换(3) Rxjava2 ...

  • Rxjava2 简析Flowable背压(4)

    Rxjava2 基本用法(1) Rxjava2 操作符原理(2) Rxjava2 线程切换(3) Rxjava2 ...

  • RxJava源码分析之线程调度(一)

    RxJava强大的地方之一是他的链式调用,轻松地在线程之间进行切换。这几天也大概分析了一下RxJava的线程切换的...

  • 安卓第三方组件收集

    要点:如果不是必须, 用系统控件 RxJava 线程切换需要注意的地方 RxJava 内置的线程调度器的确可以让我...

  • RxJava:线程切换

    上一篇:RxJava:基本订阅流程 我们在Rxjava中最常用的两个方法: subscribeOn(Schedul...

网友评论

      本文标题:RxJava线程切换的问题

      本文链接:https://www.haomeiwen.com/subject/xmvyxftx.html