Reputation: 195
We are using Akavache on project, in Android everything works great but on iOS we had some issue that is if we save a key value in the cache like this:
public async void Salvar(Login login)
{
await BlobCache.LocalMachine.InsertObject("login", login);
}
BlobCache will save without erros, if i stop the debug session, and start again the debug and try do get the value using:
public async Task<Login> Recuperar()
{
try
{
var dados = await BlobCache.LocalMachine.GetObject<Login>("login");
return dados;
}
catch (KeyNotFoundException)
{
return null;
}
}
i will get the KeyNotFoundException, i dont know why in Android works great but on iOS seeams that the database is gone after restart the app.
in my Xamarin config on Visual Studio check Preserve application data/cache on device between deploys is true and my
BlobCache.ApplicationName = "AppName";
at OnStar Method
Anyone knows what is happening? thanks
Upvotes: 1
Views: 1019
Reputation: 1
Your problem is the use of "Local Machine"
Xamarin.iOS may remove data, stored in BlobCache.LocalMachine, to free up disk space (only if your app is not running). The locations BlobCache.UserAccount and BlobCache.Secure will be backed up to iCloud and iTunes.
Xamarin.Android may also start deleting data, stored in BlobCache.LocalMachine, if the system runs out of disk space. It isn't clearly specified if your app could be running while the system is cleaning this up.
There are four built-in locations that have some magic applied on some systems:
BlobCache.LocalMachine - Cached data. This data may get deleted without notification.
BlobCache.UserAccount - User settings. Some systems backup this data to the cloud.
BlobCache.Secure - For saving sensitive data - like credentials.
BlobCache.InMemory - A database, kept in memory. The data is stored for the lifetime of the app.
You should rather use
public async void Salvar(Login login)
{
await BlobCache.UserAccount.InsertObject("login", login);
}
[Reference: Akavache Documentations]
Upvotes: 0
Reputation: 2177
I ran into this recently and for me it was because I was missing this file https://github.com/akavache/Akavache/blob/master/src/Akavache.Sqlite3/content/AkavacheSqliteLinkerOverride.cs.pp
If anyone else comes across this issue I'd first recommend just doing what OP did and creating your own. In the end that's better but if you want to use the static ones then make sure to have a class that looks like
using System;
using Akavache.Sqlite3;
// Note: This class file is *required* for iOS to work correctly, and is
// also a good idea for Android if you enable "Link All Assemblies".
namespace SomeNameSpace
{
[Preserve]
public static class LinkerPreserve
{
static LinkerPreserve()
{
throw new Exception(typeof(SQLitePersistentBlobCache).FullName);
}
}
public class PreserveAttribute : Attribute
{
}
}
What's happening is that the resilient cache never gets swapped in and it just uses the InMemory cache by default. Which is why the data disappears on restart
Upvotes: 4
Reputation: 195
Finally solved! the problem is that the path that Akavache is using, after creating my own path the problem is solved.
1 - Create a DependencyService that get your runtime platform path like for iOS:
var documentsPath =Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var libraryPath = Path.Combine(documentsPath, "..", "Library");
var path = Path.Combine(libraryPath, "cache.db");
in your PCL init you do this:
BlobCache.ApplicationName = "AppName";
BlobCache.EnsureInitialized();
var local = DependencyService.Get<ILocalCache>();
var pathToCacheDbFile = local.GetPath();
CacheConfig.NormalCache = new SQLitePersistentBlobCache(pathToCacheDbFile);
My CacheConfig:
public class CacheConfig
{
public static bool Initialised { get; set; }
public static IBlobCache NormalCache { get; set; }
}
then you use all your caches like this:
public async Task<bool> Salvar(Login login)
{
try
{
await CacheConfig.NormalCache.InsertObject("login", login);
}
catch (Exception ex)
{
//todo
}
return true;
}
this solution is based on other threads here.
Regards
Upvotes: 2
Reputation: 178660
Only guessing, but perhaps your Salvar
method is throwing (maybe login
can't be serialized)? You won't really know that it is because you're not awaiting it. You can't be because it's returning void
rather than Task
. This is a bad practice that should be avoided wherever possible.
Change Salvar
to return Task
and be sure to await
the save.
Upvotes: 0
Reputation: 655
My guess is that since you are stoping the process in the middle " if i stop the debug session, ", you are not shutting down the cache and then losing some data.
Take a look here: https://github.com/akavache/Akavache#shutting-down
Upvotes: 0