DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Coding
  3. Frameworks
  4. Xamarin.Forms, Akavache, and I: Initial Setup

Xamarin.Forms, Akavache, and I: Initial Setup

In this series, we'll see how to make use of the Akavache caching solution with Xamarin, starting with getting everything set up and ready to go.

Marco Siccardi user avatar by
Marco Siccardi
·
May. 10, 18 · Tutorial
Like (1)
Save
Tweet
Share
15.74K Views

Join the DZone community and get the full member experience.

Join For Free

Caching is never a trivial task. Sometimes, we can use built-in storage, but more often, these take quite some time when we are storing a large amount of data (e.g. large datasets or large JSON strings). I tried quite a few approaches, including:

  • Built-in storage
  • Self-handled files
  • Plugins that use one or both of the above
  • Akavache (which uses SQLite under the hood)

Why Akavache Wins

Well, the major reason is quite easy. It is fast. Really fast - at least compared to the other options. You may not notice the difference until you are using a background task that relies on the cached data or until you try to truly optimize startup performance of your Xamarin Android app. Those were the reasons for me to switch because once implemented, it does handle both jobs perfectly. Because it is so fast, there are quite a lot of apps that use it. Bonus: there are a lot of tips on StackOverflow as well as on GitHub, as it is already used by a lot of developers.

Getting Your Projects Ready

Well, as often, it all starts with the installation of NuGet packages. As I am trying to follow good practices wherever I can, I am using .netStandard whenever possible. The latest stable version of Akavache does work partially in .netStandard projects, but I recommend to use the latest alpha (by the time of this post) in your .netStandard project (even if VisualStudio keeps telling you that a pre-release dependency is not a good idea). If you are using the package reference in your project files, there might be some additional work to bring everything to build and run smoothly, especially in a Xamarin.Android project.

Your mileage may vary, but in my experience, you should install the following dependencies and Akavache separately:

  • System.Reactive, version 3.1.1
  • Splat, version 3.0 (4.0 has been available for a few days, but I didn’t test it yet)
  • SQLitePCLRaw.bundle_e_sqlite3, version 1.1.10
  • akavache.sqlite3, version 6.0.0-alpha0038
  • akavache.core, version 6.0.0-alpha0038
  • akavache, version 6.0.0-alpha0038

After installing these packages in your Xamarin.Forms and platform projects, we are ready for the next step.

Initializing Akavache

Basically, you should be able to use Akavache very simply by just defining the application name like this during application initialization:

BlobCache.ApplicationName = "MyAkavachePoweredApp";

You can do this assignment in your platform project as well as in your Xamarin.Forms project; both ways will work. Just remember to do this, as to get my code working, this is a needed step.

There are static properties like BlobCache.LocalMachine one can use to cache data. However, once your app uses an advanced library like Akavache, it is very likely that the complexity of your app will force you into a more complex scenario. In my case, the use of a scheduled job on Android was the reason why I did the initialization on my own. The scheduled job starts a process for the application and the job updates data in the cache that the application uses. There were several cases where the standard initialization did not work, so I decided to make the special case to a standard case. The following code will also work in simple scenarios but keeps doors open for more complex ones as well. The second reason why I did my own implementation is the MVVM structure of my apps.

IBlobCacheInstanceHelper Rules Them All

When we want to use platform implementations, it all starts with an interface that dictates the functionality. Let's start with this simple one:

public interface IBlobCacheInstanceHelper
{
    void Init();
    IBlobCache LocalMachineCache { get; set; }
}

We are defining our own IBlobCacheinstance, which we will initialize with the Init() method on each platform. Let's have a look on the platform implementations:

[assembly: Xamarin.Forms.Dependency(typeof(PlatformBlobCacheInstanceHelper))]
namespace [YOURNAMESPACEHERE]
{
    public class PlatformBlobCacheInstanceHelper : IBlobCacheInstanceHelper
    {
        private IFilesystemProvider _filesystemProvider;

        public PlatformBlobCacheInstanceHelper() { }

        public void Init()
        {
            _filesystemProvider = Locator.Current.GetService<IFilesystemProvider>();
            GetLocalMachineCache();
        }

        public IBlobCache LocalMachineCache { get; set; }

        private void GetLocalMachineCache()
        {

            var localCache = new Lazy<IBlobCache>(() => 
                                                  {
                                                      _filesystemProvider.CreateRecursive(_filesystemProvider.GetDefaultLocalMachineCacheDirectory()).SubscribeOn(BlobCache.TaskpoolScheduler).Wait();
                                                      return new SQLitePersistentBlobCache(Path.Combine(_filesystemProvider.GetDefaultLocalMachineCacheDirectory(), "blobs.db"), BlobCache.TaskpoolScheduler);
                                                  });

            this.LocalMachineCache = localCache.Value;
        }

        //TODO: implement other cache types if necessary at some point
    }
}

Let me explain what this code does.

As SQLite, which is powering Akavache, is file based, we need to provide a file path. The Init() method assigns Akavache's internal IFileSystemProviderinterface to the internal member. After getting an instance via Splat's Locator, we can now use it to get the file path and create the .db-file for our local cache. The GetLocalMachineCache()method is basically a copy of Akavache's internal registration. It lazily creates an instance of BlobCache through the IBlobCacheinterface. The create instance is then passed to the LocalMachineCacheproperty, which we will use later on. Finally, we will be using the DependencyService of Xamarin.Forms to get an instance of our platform implementation, which is why we need to define the Dependency attribute as well.

Note: you can name the file whatever you want. If you are already using Akavache and want to change the instance handling, you should keep the original names used by Akavache. This way, your users will not lose any data.

This implementation can be used for your Android, iOS, and UWP projects within your Xamarin.Forms app. If you are wondering why I do this separately for every platform, you are right. Until now, there is no need to do it that way. The code above would also work solely in your Xamarin.Forms project. Once you are coming to the point where you need encrypted data in your cache, the platform implementations will change on every platform. This will be topic of a future blog post, however.

If you have been reading my series about MVVMLight, you may guess the next step already. This is how I initialize the platform implementation within my ViewModelLocator:

//register:
var cacheInstanceHelper = DependencyService.Get<IBlobCacheInstanceHelper>();
if (!SimpleIoc.Default.IsRegistered<IBlobCacheInstanceHelper>())
     SimpleIoc.Default.Register<IBlobCacheInstanceHelper>(()=> cacheInstanceHelper);

//initialize:
//cacheInstanceHelper.Init();
//or
SimpleIoc.Default.GetInstance<IBlobCacheInstanceHelper>().Init();

So that's it, we are now ready to use our local cache powered by Akavache within our Xamarin.Forms project. In the next post, we will have a look at how to use Akavache for storing and retrieving data.

Until then, happy coding, everyone!

xamarin.forms

Published at DZone with permission of Marco Siccardi, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Using AI and Machine Learning To Create Software
  • PHP vs React
  • Automated Performance Testing With ArgoCD and Iter8
  • Writing a Modern HTTP(S) Tunnel in Rust

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: