MonkeyCacheを使ったデータのキャッシュ Xamarin.Formsで
公式↓ montemagno.com
MonkeyCacheはウェブから取得したデータをキャッシュして,必要に応じて利用することを助けるライブラリです.
データのキャッシュとは,オンライン時にWebAPIなどから取得したデータをローカルに保持しておき,オフライン時にはキャッシュからデータを取り出して表示したり,または不要なデータの取得による通信の発生を低減したりできます.
MonkeyCacheを使うことで,このようなキャッシュの仕組みを簡単に利用できます.
キャッシュしたデータの有効期限を指定することで,有効期限が切れていた場合はWebからデータを取得するといった処理もできます.
MonkeyCacheのインストール
MonkeyCacheには3種類あって,キャッシュするデータの保存先によって異なります.
一番シンプルなのはファイルへの保存なので,今回はMonkeyCache.FileStoreをインストールします.
WebAPIからデータを取得する機能を用意する
WebAPIを利用してデータを取得する際に便利なので,先にSystem.Net.Http.Json
をインストールしておきます.
WebAPIからデータを取得する機能はHttpClient
を使って,WebAPIからデータを取得するか,もしくは有効なキャッシュデータがあればそれを取得して呼び出しもとに返すシンプルなものです.
ソースコードは以下のとおりです.
using MonkeyCache; using MonkeyCache.FileStore; using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Json; using System.Text; using System.Threading.Tasks; using Xamarin.Essentials; using Xamarin.Forms; using XFCacheDataPractice.Models.Covid19; using XFCacheDataPractice.Services; [assembly: Dependency(typeof(Covid19JapanApiManager))] namespace XFCacheDataPractice.Services { public class Covid19JapanApiManager { private IBarrel _barrel; private readonly HttpClient _httpClient; public Covid19JapanApiManager() { //HttpClientの生成 //Covid19JapanApiManagerクラスはDependencyService経由でインスタンスを取得するので //1回しか生成されないので大丈夫. this._httpClient = new HttpClient { BaseAddress = new Uri("https://covid19-japan-web-api.now.sh/api/v1/") }; Barrel.ApplicationId = AppInfo.PackageName; this._barrel = Barrel.Create(FileSystem.AppDataDirectory); } //県別のデータをMonkeyCacheに格納,取得する際のキー public const string CachePrefecturesKey = "get_prefectures"; /// <summary> /// WebAPIから県別のデータを取得する. /// </summary> /// <returns></returns> public async Task<IEnumerable<Prefecture>> GetPrefectures() { try { //キャッシュが存在して,有効期間内の場合はキャッシュから if (!_barrel.IsExpired(key: CachePrefecturesKey)) { await Task.Yield(); return _barrel.Get<IEnumerable<Prefecture>>(key: CachePrefecturesKey); } //インターネットに接続してれば取得 if (Connectivity.NetworkAccess == NetworkAccess.Internet) { //WebAPIからデータ取得 var prefecturesData = await _httpClient.GetFromJsonAsync<IEnumerable<Prefecture>>("prefectures"); //キャッシュを更新.キャッシュの有効期限を設定 _barrel.Add(key: CachePrefecturesKey, data: prefecturesData, expireIn: TimeSpan.FromMinutes(10)); return prefecturesData; } //インターネットにも接続してないし,キャッシュも有効期限切れだった場合 //それでも有効期限切れのキャッシュデータを返すか. if (_barrel.Exists(key: CachePrefecturesKey)) { //とりあえず返すことにした. return _barrel.Get<IEnumerable<Prefecture>>(key: CachePrefecturesKey); } return new List<Prefecture>(); } catch { throw; } } } }
MonkeyCacheの使い方
MonkeyCacheではデータをキーとともにBarrel(樽)というオブジェクトに入れたり出したりするシンプルなものです.
データを格納する際に有効期限を設定でき,有効期限内か有効期限切れかをチェックすることができます.利用者は,有効期限切れの際にはWebAPIからデータを再取得する,などを判断して実装することができます.
利用前の初期化
Barre.ApplicationIdに任意のユニークな文字列を設定します.Xamarin.EssentialsのAppInfo.PackageName
でアプリケーションのパッケージ名を指定すれば良いでしょう.
Barrel.ApplicationId = AppInfo.PackageName;
次に,Barrelインスタンスをキャッシュ保存先のディレクトリのパスとともに生成します.
this._barrel = Barrel.Create(FileSystem.AppDataDirectory);
保存先のディレクトリはXamarin.EssentialsのFileSystem.AppDataDirectory
を使うと良いでしょう.
Barrelのインスタンスですが,Create
メソッドを使わずともBarrel.Current
プロパティがSingletonでインスタンスを返してくれるようになっているので,保存先をおまかせするのであればCreate
メソッドを使う必要はなく,以後のデータ格納,取得はBarrel.Current経由で行っても大丈夫です.
その場合は,MonkeyCacheのソースコードによると,以下のように各プラットフォーム毎に用意されているキャッシュ専用のディレクトリが使用されるようになっています.
#if __IOS__ || __MACOS__ basePath = NSSearchPath.GetDirectories(NSSearchPathDirectory.CachesDirectory, NSSearchPathDomain.User)[0]; #elif __ANDROID__ basePath = Application.Context.CacheDir.AbsolutePath; #elif __UWP__ basePath = Windows.Storage.ApplicationData.Current.LocalCacheFolder.Path; #else basePath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); #endif
これで利用の準備が整いました.
データの格納
Barrelインスタンスに対してAdd
メソッドでデータを格納します.
//キャッシュを更新.キャッシュの有効期限を設定 _barrel.Add(key: CachePrefecturesKey, data: prefecturesData, expireIn: TimeSpan.FromMinutes(10)); //もしくはBarrel.Current.Add(....
KeyとDataと有効期限をメソッドに渡すだけです.
Keyは任意の文字列,Dataはオブジェクトをそのまま,有効期限はTimeSpanで.ここでは有効期限を10分間にしています.
これでデータのキャッシュが完了です.
データの取得
格納したキャッシュデータを取り出す場合はGet
メソッドを使います.
_barrel.Get<IEnumerable<Prefecture>>(key: CachePrefecturesKey);
//もしくはBarrel.Current.Get<.....
型引数に取り出したいデータの型を指定し,データ格納時に使用したKeyを指定することでデータを取得できます.
データが有効期限内か否かを確認する
データが指定した有効期限内か否かを確認するためにはIsExpired
メソッドを使います.
_barrel.IsExpired(key: CachePrefecturesKey)
//もしくはBarrel.Current.IsExpired(...
パラメータにデータ格納時に指定したKeyを指定することで,そのデータが有効期限内か否かをbool値で返してくれます.
使い方は以上のように至ってシンプルです.