我们在Android App中使用mutliple服务。这些服务将其数据提供为无限Observables
,通常通过组合Observables
其他服务来构建。
这些Observables
的构建成本很高。此外,服务通常在多个地方消费,因此他们的Observable
应该在订阅者之间共享。
LocationService
,提供无限Observable<Location>
,发出当前位置ReminderService
,提供无限Observable<List<Reminder>>
,在数据集中的每次更改后发出所有存储的提醒列表LocationAwareReminderService
,通过Observable<List<Reminders>>
前两项服务的Observable.combineLatest
提供无限Observables
个附近提醒每个服务都会将消费的Observables
组合在一起,并将其内部BehaviorSubject
订阅到生成的Feed中。然后,消费者可以订阅此BehaviorSubject
。
例如LocationAwareReminderService
:
public class LocationAwareReminderService {
Observable<List<Reminder>> feed;
public LocationAwareReminderService(ReminderService reminderService, LocationService locationService) {
BehaviorSubject<List<Reminder>> cache = BehaviorSubject.create();
Observable.combineLatest(reminderService.getFeed(), locationService.getFeed(), new Func2<List<Reminder>, Location, List<Reminder>>() {
@Override
public List<Reminder> call(List<Reminder> reminders, Location location) {
return calculateNearbyReminders(reminders, location);
}
}).subscribe(cache);
feed = cache.asObservable();
}
public Observable<List<Reminder>> getFeed() {
return feed;
}
}
缺点:
优势:
public class LocationAwareReminderService {
Observable<List<Reminder>> feed;
public LocationAwareReminderService(ReminderService reminderService, LocationService locationService) {
feed = Observable.combineLatest(reminderService.getFeed(), locationService.getFeed(), new Func2<List<Reminder>, Location, List<Reminder>>() {
@Override
public List<Reminder> call(List<Reminder> reminders, Location location) {
return calculateNearbyReminders(reminders, location);
}
}).replay(1).refCount();
}
public Observable<List<Reminder>> getFeed() {
return feed;
}
}
缺点:
Subscriber
整个管道崩溃的短期。在下一次订阅期间,需要重建整个管道。Activity
A到Activity
B的转换,都订阅了LocationAwareReminderService.getFeed()
,导致管道完全取消和重建优势:
Subscriber
取消订阅后,LocationAwareReminderService
也会取消订阅LocationService.getFeed()
和reminderService.getFeed()
Observables
。LocationAwareReminderService
仅在第一个Subscriber
订阅后才开始提供附近的提醒Subscriber
s 因此我构建了一个Transformer
,使订阅在最后Subscriber
取消订阅
public class RxPublishTimeoutCache<T> implements Observable.Transformer<T, T> {
private long keepAlive;
private TimeUnit timeUnit;
public RxPublishTimeoutCache(long keepAlive, TimeUnit timeUnit) {
this.keepAlive = keepAlive;
this.timeUnit = timeUnit;
}
@Override
public Observable<T> call(Observable<T> upstream) {
final Observable<T> sharedUpstream = upstream.replay(1).refCount();
return Observable.create(new Observable.OnSubscribe<T>() {
@Override
public void call(Subscriber<? super T> subscriber) {
if (subscriber.isUnsubscribed())
return;
// subscribe an empty Subscriber that keeps the subsription of refCount() alive
final Subscription keepAliveSubscription = sharedUpstream.subscribe(new NopSubscriber<T>());
// listen to unsubscribe from the subscriber
subscriber.add(Subscriptions.create(new Action0() {
@Override
public void call() {
// the subscriber unsubscribed
Observable.timer(keepAlive, timeUnit).subscribe(new Action1<Long>() {
@Override
public void call(Long _) {
// unsubscribe the keep alive subscription
keepAliveSubscription.unsubscribe();
}
});
}
}));
sharedUpstream.subscribe(subscriber);
}
});
}
public class NopSubscriber<T> extends Subscriber<T> {
@Override
public void onCompleted() {}
@Override
public void onError(Throwable e) {}
@Override
public void onNext(T o) {}
}
}
LocationAwareReminderService
使用RxPublishTimeoutCache
public class LocationAwareReminderService {
Observable<List<Reminder>> feed;
public LocationAwareReminderService(ReminderService reminderService, LocationService locationService) {
feed = Observable.combineLatest(reminderService.getFeed(), locationService.getFeed(), new Func2<List<Reminder>, Location, List<Reminder>>() {
@Override
public List<Reminder> call(List<Reminder> reminders, Location location) {
return calculateNearbyReminders(reminders, location);
}
}).compose(new RxPublishTimeoutCache<List<Reminder>>(10, TimeUnit.SECONDS));
}
public Observable<List<Reminder>> getFeed() {
return feed;
}
}
优势:
LocationAwareReminderService
仅在第一个Subscriber
订阅后才开始提供附近的提醒缺点:
RxPublishTimeoutCache
?答案 0 :(得分:2)
我认为这是一个有趣的问题,似乎是一个有用的操作符,因此我在rxjava-extras中创建了var image = new BitmapImage();
using (var stream = await element.RenderToRandomAccessStream())
{
image.SetSource(stream);
}
ImageBrush ib = new ImageBrush();
ib.ImageSource = splitViewBlurImage;
ib.Stretch = Stretch.UniformToFill;
splitViewSideBarBlur.Source = splitViewBlurImage;
splitViewSideBarBlur.VerticalAlignment = VerticalAlignment.Top;
var graphicsEffect = new BlendEffect
{
Background = new ColorSourceEffect()
{
Name = "Tint",
Color = Color.FromArgb(95, 255, 255, 255)
},
Foreground = new GaussianBlurEffect()
{
Name = "Blur",
Source = new CompositionEffectSourceParameter("Backdrop"),
BlurAmount = (float)20,
BorderMode = EffectBorderMode.Hard,
}
};
var blurEffectFactory = _compositor.CreateEffectFactory(graphicsEffect,
new[] { "Blur.BlurAmount", "Tint.Color" });
_brush = blurEffectFactory.CreateBrush();
var destinationBrush = _compositor.CreateBackdropBrush();
_brush.SetSourceParameter("Backdrop", destinationBrush);
var blurSprite = _compositor.CreateSpriteVisual();
blurSprite.Size = new Vector2((float)splitViewSideBarBlur.ActualWidth, (float)splitViewSideBarBlur.ActualHeight);
blurSprite.Brush = _brush;
this.splitViewSideBarBlur.Source = null;
ElementCompositionPreview.SetElementChildVisual(this.splitViewSideBarBlur, blurSprite);
:
Transformers.delayFinalUnsubscribe
它可以在Maven Central的0.7.9.1的rxjava-extras中找到。如果你愿意,可以给它一个旋转,看看是否有任何问题。
答案 1 :(得分:0)
现在,refCount的重载需要超时,而这恰好做到了