我写了一个小测试来重现我的问题。我想嵌套缓存的observable并反映对ORIGINAL对象所做的基础数据结构所做的所有更改,但是使用嵌套缓存这似乎失败了。
有可能解决问题吗?我写了我在期待的问题......
测试
public static void test()
{
// --------------------
// TEST 1 - simple caching
// --------------------
List<Data> emptyData1 = getEmptyData()
.toBlocking()
.single();
L.d("TEST 1a - Size: %d == %d", emptyData1.size(), 0);
// add 1 empty data
emptyData1.add(new Data(0, false));
L.d("TEST 1b - Size: %d == %d (Loaded: %b)", emptyData1.size(), 1, emptyData1.get(0).loaded);
List<Data> emptyData2 = getEmptyData()
.toBlocking()
.single();
L.d("TEST 1c - Size: %d == %d (Loaded: %b)", emptyData2.size(), 1, emptyData2.get(0).loaded);
// --------------------
// TEST 2 - nested caching
// --------------------
List<Data> loadedData1 = getLoadedData()
.toBlocking()
.single();
L.d("TEST 2a - Size: %d == %d (Loaded: %b)", loadedData1.size(), 1, loadedData1.get(0).loaded);
// add a second data, this time we add a loaded data
loadedData1.add(new Data(1, true));
List<Data> loadedData2 = getLoadedData()
.toBlocking()
.single();
L.d("TEST 2b - Size: %d == %d (Loaded: %b, %b)", loadedData1.size(), 2, loadedData2.get(0).loaded, loadedData2.get(1).loaded);
// --------------------
// TEST 3 - test if empty observable is holding the loaded data as well now
// --------------------
List<Data> testEmptyStateData = getEmptyData()
.toBlocking()
.single();
L.d("TEST 3a - Size: %d == %d", testEmptyStateData.size(), 2);
// I don't expect this, but this will happen
if (testEmptyStateData.size() == 1)
{
L.d("TEST 3b1 - Size: %d == %d (Loaded: %b)", testEmptyStateData.size(), 2, testEmptyStateData.get(0).loaded);
}
// I expect this, but it won't be true
if (testEmptyStateData.size() == 2)
{
L.d("TEST 3b - Size: %d == %d (Loaded: %b, %b)", testEmptyStateData.size(), 2, testEmptyStateData.get(0).loaded, testEmptyStateData.get(1).loaded);
}
}
结果
TEST 1a - Size: 0 == 0
TEST 1b - Size: 1 == 1 (Loaded: false)
TEST 1c - Size: 1 == 1 (Loaded: false)
TEST 2a - Size: 1 == 1 (Loaded: true)
TEST 2b - Size: 2 == 2 (Loaded: true, true)
TEST 3a - Size: 1 == 2 // <= UNDESIRED RESULT!!!
TEST 3b1 - Size: 1 == 2 (Loaded: true) // <= at least the object in the list is correct! But I would expect that the empty observalbe would hold 2 items, both loaded! "Test 3b2" should be printed instead
问题
我希望所有的observable都只是将ORIGINAL List传递给流,并且我总是得到原始对象,并且我对该对象的所有更改都将反映在基本列表中,因此最后,空的observable应返回2个已加载的数据项,但对于此嵌套缓存方案而言则不然。
我需要什么
cache()
代码
助手功能和数据
private static Observable<List<Data>> mEmptyObservable = null;
private static Observable<List<Data>> mLoadedObservable = null;
public static Observable<List<Data>> getEmptyData()
{
if (mEmptyObservable == null)
{
// simple test data
List<Data> values = new ArrayList<>();
mEmptyObservable = Observable.just(values)
// cache and share observable
.cache().replay().refCount();
}
return mEmptyObservable;
}
public static Observable<List<Data>> getLoadedData()
{
if (mLoadedObservable == null)
{
mLoadedObservable = getEmptyData()
.flatMap(new Func1<List<Data>, Observable<Data>>()
{
@Override
public Observable<Data> call(List<Data> datas)
{
return Observable.from(datas);
}
})
.map(new Func1<Data, Data>()
{
@Override
public Data call(Data data)
{
data.load();
return data;
}
})
.toList()
// cache and share observable
.cache().replay().refCount();
}
return mLoadedObservable;
}
数据类
static class Data
{
int index;
boolean loaded;
public Data(int index, boolean processed)
{
this.index = index;
this.loaded = processed;
}
public void load()
{
if (!loaded)
{
// do some have operation... once only per data!
}
loaded = true;
}
}
答案 0 :(得分:1)
您同时使用cache()
和replay()
。尝试像
private static Observable<List<Data>> mEmptyObservable = null;
private static Observable<List<Data>> mLoadedObservable = null;
public static Observable<List<Data>> getEmptyData()
{
if (mEmptyObservable == null)
{
// simple test data
List<Data> values = new ArrayList<>();
mEmptyObservable = Observable.just(values)
// share and replay observable
.share().replay();
}
return mEmptyObservable;
}
public static Observable<List<Data>> getLoadedData()
{
if (mLoadedObservable == null)
{
mLoadedObservable = getEmptyData()
.flatMap(new Func1<List<Data>, Observable<Data>>()
{
@Override
public Observable<Data> call(List<Data> datas)
{
return Observable.from(datas);
}
})
.map(new Func1<Data, Data>()
{
@Override
public Data call(Data data)
{
data.load();
return data;
}
})
.toList()
// share and replay observable
.share().replay();
}
return mLoadedObservable;
}
this answer中有更多信息。
编辑:但真正的问题似乎是你在getLoadedData()中创建了一个不同的列表。如果你想要相同的列表尝试类似
public static Observable<List<Data>> getLoadedData()
{
if (mLoadedObservable == null)
{
mLoadedObservable = getEmptyData().
.map(new Func1<List<Data>, List<Data>>()
{
@Override
public Data call(List<Data> data)
{
for (Data item : data) {
item.load();
}
return data;
}
})
// share and replay observable
.share().replay();
}
return mLoadedObservable;
}