如何在Android中创建Observable?

8

我想做的是创建一个简单的内存缓存,以尝试使用Observables。然而,我卡在了创建Observable上,不太明白该怎么做。这是我目前的代码:

public class MovieCache {
    MovieWrapper movieWrapper;

    public Observable<MovieWrapper> getMovies() {
       //How to create and return an Observable<MovieWrapper> here?
    }

    public void setCache(MovieWrapper wrapper) {
        movieWrapper = wrapper;
    }

    public void clearCache() {
        movieWrapper = null;
    }
}

getMovies()方法中,我想创建一个Observable并将我的本地变量movieWrapper返回给subscriber。我该怎么做?我尝试使用new Observable.just(movieWrapper),但结果出现了空指针异常。

2个回答

7
请查看这篇教程,它正好介绍了你想要的内容。基本上,你需要使用defer()确保你始终得到你缓存对象的最新版本。
public class MovieCache {
    MovieWrapper movieWrapper;

    public Observable<MovieWrapper> getMovies() {  
        return Observable.defer(new Func0<Observable<MovieWrapper>>() {
            @Override
            public Observable<MovieWrapper> call() {
                return Observable.just(movieWrapper);
            }
        });
    }

    public void setCache(MovieWrapper wrapper) {
        movieWrapper = wrapper;
    }

    public void clearCache() {
        movieWrapper = null;
    }
}
defer() 确保你只在 订阅 Observable 而不是在 创建 时获取对象。值得注意的是,根据该文章的作者所说:

唯一的缺点是每当你获得一个订阅者时,它就会创建一个新的 Observable。create() 可以为每个订阅者使用相同的函数,因此更有效率。一如既往,如果需要,请测量性能并进行优化。


4
正如之前所述,接受的答案有缺点:每次获取订阅者时都会创建一个新的Observable。但这并不是唯一的缺点。
  • 如果在调用setCache(...)之前调用getMovies().subscribe(...),则消费者将不会收到任何值。
  • 如果想要接收任何更新(比方说setCache()可以被多次调用),则消费者应该重新订阅。
当然,所有这些可能都与您的情况无关。我只是想向您展示另一种方式(我相信还有很多其他方式)。您可以使用BehaviorSubject来消除所有这些缺点。
public class MovieCache {
    private BehaviorSubject<MovieWrapper> mMovieCache = BehaviorSubject.create();

    public void setCache(MovieWrapper wrapper) {
        mMovieCache.onNext(wrapper);
    }

    public Observable<MovieWrapper> getMovieObservable() {
        //use this if consumer want to receive all updates
        return mMovieCache.asObservable();
    }

    public MovieWrapper getMovie() {
        //use this if consumer want to get only current value
        //and not interested in updates
        return mMovieCache.getValue();
    }

    public void clearCache() {
        //CAUTION consumer should be ready to receive null value
        mMovieCache.onNext(null);
        //another way is to call mMovieCache.onCompleted();
        //in this case consumer should be ready to resubcribe
    }

    public static class MovieWrapper {}

}

请看BehaviorSubject弹珠图

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接