简短版本:如何在我自己的代码(https://github.com/akavache/Akavache/blob/501b397d8c071366c3b6783aae3e98695b3d7442/src/Akavache/Portable/JsonSerializationMixin.cs#L202)中实现像Akavache这样的GetAndFetchLatest
方法 - 就像没有添加Akavache一样?
长版:
我有一个从磁盘返回T列表的方法,我有一个从HTTP服务返回相同类型List<T>
的方法。
两者都异步包装为Task<List<T>>
在我的视图模型中,我只想调用1返回Observable<List<T>>
的方法。
因此,在我的ViewModel中,我使用.Subscribe()
方法更新UI。
实质上,我需要两次通知数据可用,订阅中的代码也将完成两次。
这个功能在Akavache中以GetAndFetchLatest
方法的形式提供......但是我不太熟悉RX,以了解我如何使用我的2个数据方法调用来实现它。
注意:所以我不想等待这两项任务!我希望同时触发两者,并在数据返回后立即通知Observable
。
任何提示?
答案 0 :(得分:3)
鉴于Task<List<T>> GetFromWeb()
和Task<List<T>> GetFromDisk()
,答案很简单:
var merged = Observable.Merge(
GetFromWeb().ToObservable(),
GetFromDisk().ToObservable()
);
//Same thing using extension syntax
var simply = GetFromWeb().ToObservable()
.Merge(GetFromDisk().ToObservable());
但是,这不会处理GetFromWeb
在GetFromDisk
之前完成的不太可能但可能的情况,在这种情况下,我假设您要忽略GetFromDisk
的结果。为了解决这个问题,你需要一些体操:
public IObservable<T> Prioritize<T>(params IObservable<T>[] orderedByDescendingPriority)
{
return orderedByDescendingPriority
.Select((o, i) => o.Select(item => Tuple.Create(orderedByDescendingPriority.Length - i, item)))
.Merge()
.Select(t => new Func<Tuple<int, T, bool>, Tuple<int, T, bool>>(t2 => Tuple.Create(Math.Max(t2.Item1, t.Item1), t.Item2, t.Item1 >= t2.Item1)))
.Scan(Tuple.Create(0, default(T), false), (t, f) => f(t))
.Where(t => t.Item3)
.Select(t => t.Item2);
}
var merged = Prioritize(
GetFromWeb().ToObservable(),
GetFromDisk().ToObservable()
);
修改强>:
如果您始终希望GetFromDisk
始终显示在GetFromWeb
之前,那么这是一个简单的Concat
操作。这是有效的,因为.NET任务会在您引用其功能后自动启动:
var t1 = GetFromDisk();
var t2 = GetFromWeb();
var merged = Observable.Concat(
t1.ToObservable(),
t2.ToObservable()
);