我阅读了大量有关Rx的文献,一方面,一切都很清楚,但另一方面,没有什么是清楚的。我尝试使用此库从服务器进行简单的过滤和存储数据,但是它没有按预期工作。我需要实现一个简单的频道列表管理:
1. Cache on disk and in memory
2. When user requested - return filtered channels
3. All Subscribers that was attached to this Observable must be notified if filtered cahnnels list was changed (call onNext() for all Subscribers)
我写了以下内容:
ArrayList<Channel> channels = null;
ArrayList<Channel> filteredChannels = null;
Observable<ArrayList<Channel>> filteredObservable = Observable.create()
// here I need to check if cache is valid, if no - download from server
// then filter channels and return filteredChannels in onNext call
// all subscribers that called subscribe before and not called unsubscribe must be notified if filteredChannels changed
// how to implement this?
.subscribeOn(Schedulers.io());
public void setFilter(Filter filter) {
// update filteredChannels with the new filter and notify all Subscribers (call onNext()). How to implement this?
}
public Observable<ArrayList<Channel>> getFilteredChannels() {
return filteredObservable;
}
我是否正确理解了Rx模式的逻辑?提前谢谢。
答案 0 :(得分:0)
我会使用.map()
的功能来过滤您的列表,然后返回您想要的输出。这意味着您的Observable将发出过滤结果。
然后,您可以将已过滤的列表提交到.subscribe()
函数中的缓存中。
答案 1 :(得分:0)
我找到了此任务的解决方案:我需要使用flatMap
和map
,我尝试使用BehaviourSubject
通知所有订阅者变量,但此解决方案不稳定根本就是因为错误MissingBackpressureException
,这就是我写下一个ObsevableValue类的原因:
public class ObservableValue<T> {
private static final String TAG = ObservableValue.class.getSimpleName();
private ArrayList<Registration> subscriptions = new ArrayList<>();
private T value;
private int index;
private boolean firstNotify;
private ReentrantLock lock = new ReentrantLock();
public ObservableValue() {
firstNotify = false;
}
public ObservableValue(T defaultValue) {
value = defaultValue;
firstNotify = true;
}
@SuppressWarnings("unchecked")
public void setValue(T value) {
lock.lock();
this.value = value;
for (Registration listener: subscriptions) {
if (!listener.isFinished()) {
listener.getListener().valueChanged(value);
}
}
lock.unlock();
}
public T getValue() {
lock.lock();
T result = value;
lock.unlock();
return result;
}
public Registration subscribe(ValueChangeListener<T> listener) {
lock.lock();
Registration s = new Registration(this, index, listener);
index++;
subscriptions.add(s);
if (firstNotify||value!=null) {
listener.valueChanged(value);
}
lock.unlock();
return s;
}
protected void finish(int index) {
lock.lock();
for (int i=0;i<subscriptions.size();i++) {
Registration s = subscriptions.get(i);
if (s.getIndex()==index) {
subscriptions.remove(i);
break;
}
}
lock.unlock();
}
}
public abstract class ValueChangeListener<T> {
private Looper looper;
public ValueChangeListener() {}
public ValueChangeListener(Looper looper) {
this.looper = looper;
}
public void valueChanged(T data) {
if (looper!=null) {
Handler handler = new Handler(looper, msg -> {
onValueChanged(data);
return true;
});
handler.sendEmptyMessage(0);
} else {
onValueChanged(data);
}
}
public abstract void onValueChanged(T data);
}
public class Registration {
private ObservableValue observableValue;
private int index;
private ValueChangeListener listener;
private volatile boolean finished = false;
protected Registration(ObservableValue observableValue, int index, ValueChangeListener listener) {
this.observableValue = observableValue;
this.index = index;
this.listener = listener;
}
protected ValueChangeListener getListener() {
return listener;
}
protected int getIndex() {
return index;
}
public boolean isFinished() {
return finished;
}
public void finish() {
finished = true;
observableValue.finish(index);
}
}
现在它按预期工作了。与Rx中一样,ObservableValue返回一个Registration对象,当不再需要它时需要finished()
。