Akavache 总是调用 fetchFunc
Akavache always calling the fetchFunc
我在 Xamarin 应用程序中有以下使用 Akavache 的代码,它的行为方式与我认为的不一样。可能是我对它应该如何的误解,但这让我发疯。
所以在我的视图模型中,我正在调用 FetchNewsCategories 并为该项目指定 5 分钟的缓存。我希望发生的是,如果缓存项不存在,它会调用 fetchFunc(即 FetchNewsCategoriesAsync),但如果我在缓存超时 5 分钟内多次调用该服务,它应该只给我缓存的项目而不进行服务器调用。在我尝试过的所有情况下,它都会继续执行剩余调用并且从不给我缓存的项目。我也用 GetAndFetchLatest 尝试过这个,如果有缓存项,它不会进行其余调用,但它也不会在视图模型的订阅事件中进行调用。
知道我在这里做错了什么吗?
编辑:我在 Android (Nexus 5 KitKat API19) 上测试了相同的代码,它运行完美。我要重置我的 IOS 模拟器,看看是不是出了什么问题。
NewsService.cs
public static async Task<ServiceResponse<List<ArticleCategoryInfo>>> FetchNewsCategoriesAsync(BlogSourceType blogSource)
{
return await ServiceClient.POST<List<ArticleCategoryInfo>>(Config.ApiUrl + "news/categories", new
{
ModuleId = Int32.Parse(Config.Values[blogSource == BlogSourceType.News ? ConfigKeys.KEY_NEWS_MODULE_ID : ConfigKeys.KEY_BLOG_MODULE_ID])
});
}
public static IObservable<ServiceResponse<List<ArticleCategoryInfo>>> FetchNewsCategories(BlogSourceType blogSource)
{
var cache = BlobCache.LocalMachine;
var cachedCategories = cache.GetOrFetchObject("categories" + blogSource,
async () => await FetchNewsCategoriesAsync(blogSource),
DateTime.Now.AddMinutes(5));
return cachedCategories;
}
NewsViewModel.cs
public async Task LoadCategories()
{
var cachedCategories = NewsService.FetchNewsCategories(blogSource);
cachedCategories.Subscribe((obj) => { Device.BeginInvokeOnMainThread(() => DisplayCategories(obj.Result,"Subscribe"));});
return;
}
private void DisplayCategories(IList<ArticleCategoryInfo> categories, string source)
{
Categories.Clear();
System.Diagnostics.Debug.WriteLine("Redisplaying categories from " + source);
foreach (var item in categories)
{
Categories.Add(item);
}
}
只是想将我的解决方案添加到我遇到的上述问题中,以供其他有此问题的人参考。
我试图缓存的 ServiceResponse
对象中有一个 HttpResponseMessage
我怀疑它导致了序列化错误,可能是循环引用,所以它从未被缓存并最终结束每次都调用端点。我最后在那个 属性 上放了一个 [IgnoreDataMemberAttribute]
所以它没有序列化,问题就消失了。
我最终按以下方式处理订阅以处理错误并确保绑定到 IsBusy
属性 的 activity 指标已正确更新。
public async Task LoadActivities(bool refresh)
{
IsBusy = true;
if (refresh) OlderThanJournalId = int.MaxValue;
var cached = ActivityService.FetchJournalItems(GroupId, OlderThanJournalId, refresh);
cached.Subscribe((result) => { Device.BeginInvokeOnMainThread(() => {
DisplayActivities(result);
}); }, (err) => HandleError(err), () => IsBusy = false);
}
public void HandleError(Exception ex) {
IsBusy = false;
DialogService.ShowErrorToast(AppResources.ErrorMessage, "Unable to load activity stream.");
System.Diagnostics.Debug.WriteLine(ex.Message);
}
private void DisplayActivities(ServiceResponse<List<JournalItem>> response)
{
if (!response.IsConnected) {
DialogService.ShowInfoToast(AppResources.ErrorMessage, AppResources.NotConnected);
return;
}
if (!response.Authorized) {
App.LoginManager.Logout();
}
Activities.Clear();
foreach (var item in response.Result)
{
Activities.Add(item);
}
}
BeginInvokeOnMainThread
用于确保在 UI.
中看到 DisplayActivities 中 ObservableCollection 的更新
我在 Xamarin 应用程序中有以下使用 Akavache 的代码,它的行为方式与我认为的不一样。可能是我对它应该如何的误解,但这让我发疯。
所以在我的视图模型中,我正在调用 FetchNewsCategories 并为该项目指定 5 分钟的缓存。我希望发生的是,如果缓存项不存在,它会调用 fetchFunc(即 FetchNewsCategoriesAsync),但如果我在缓存超时 5 分钟内多次调用该服务,它应该只给我缓存的项目而不进行服务器调用。在我尝试过的所有情况下,它都会继续执行剩余调用并且从不给我缓存的项目。我也用 GetAndFetchLatest 尝试过这个,如果有缓存项,它不会进行其余调用,但它也不会在视图模型的订阅事件中进行调用。 知道我在这里做错了什么吗?
编辑:我在 Android (Nexus 5 KitKat API19) 上测试了相同的代码,它运行完美。我要重置我的 IOS 模拟器,看看是不是出了什么问题。
NewsService.cs
public static async Task<ServiceResponse<List<ArticleCategoryInfo>>> FetchNewsCategoriesAsync(BlogSourceType blogSource)
{
return await ServiceClient.POST<List<ArticleCategoryInfo>>(Config.ApiUrl + "news/categories", new
{
ModuleId = Int32.Parse(Config.Values[blogSource == BlogSourceType.News ? ConfigKeys.KEY_NEWS_MODULE_ID : ConfigKeys.KEY_BLOG_MODULE_ID])
});
}
public static IObservable<ServiceResponse<List<ArticleCategoryInfo>>> FetchNewsCategories(BlogSourceType blogSource)
{
var cache = BlobCache.LocalMachine;
var cachedCategories = cache.GetOrFetchObject("categories" + blogSource,
async () => await FetchNewsCategoriesAsync(blogSource),
DateTime.Now.AddMinutes(5));
return cachedCategories;
}
NewsViewModel.cs
public async Task LoadCategories()
{
var cachedCategories = NewsService.FetchNewsCategories(blogSource);
cachedCategories.Subscribe((obj) => { Device.BeginInvokeOnMainThread(() => DisplayCategories(obj.Result,"Subscribe"));});
return;
}
private void DisplayCategories(IList<ArticleCategoryInfo> categories, string source)
{
Categories.Clear();
System.Diagnostics.Debug.WriteLine("Redisplaying categories from " + source);
foreach (var item in categories)
{
Categories.Add(item);
}
}
只是想将我的解决方案添加到我遇到的上述问题中,以供其他有此问题的人参考。
我试图缓存的 ServiceResponse
对象中有一个 HttpResponseMessage
我怀疑它导致了序列化错误,可能是循环引用,所以它从未被缓存并最终结束每次都调用端点。我最后在那个 属性 上放了一个 [IgnoreDataMemberAttribute]
所以它没有序列化,问题就消失了。
我最终按以下方式处理订阅以处理错误并确保绑定到 IsBusy
属性 的 activity 指标已正确更新。
public async Task LoadActivities(bool refresh)
{
IsBusy = true;
if (refresh) OlderThanJournalId = int.MaxValue;
var cached = ActivityService.FetchJournalItems(GroupId, OlderThanJournalId, refresh);
cached.Subscribe((result) => { Device.BeginInvokeOnMainThread(() => {
DisplayActivities(result);
}); }, (err) => HandleError(err), () => IsBusy = false);
}
public void HandleError(Exception ex) {
IsBusy = false;
DialogService.ShowErrorToast(AppResources.ErrorMessage, "Unable to load activity stream.");
System.Diagnostics.Debug.WriteLine(ex.Message);
}
private void DisplayActivities(ServiceResponse<List<JournalItem>> response)
{
if (!response.IsConnected) {
DialogService.ShowInfoToast(AppResources.ErrorMessage, AppResources.NotConnected);
return;
}
if (!response.Authorized) {
App.LoginManager.Logout();
}
Activities.Clear();
foreach (var item in response.Result)
{
Activities.Add(item);
}
}
BeginInvokeOnMainThread
用于确保在 UI.