Resilient Network Services – Bölüm 5 – Akavache – 2
Selamlar,
Bir önceki yazımda akavache den bahsetmiş, ne olduğundan, ne faydası olduğundan ve bazı özelliklerinden bahsetmiştim. Bu yazımda bunun devamı olarak ne şekilde kullanabileceğimize, yardımcı metodlarına değineceğim.
Tüm Akavache BlobCache leri aşağıdaki temel metodları destekliyor.
/* * Store dan dataları almak.. */ // tek bir data almak için. IObservable<byte[]> Get(string key); // dataların bir koleksiyonunu almak için. IObservable<IDictionary<string, byte[]>> Get(IEnumerable<string> keys); // eklediğiniz tipten Deserialize edilmiş tek bir datayı almak için. IObservable<T> GetObject<T>(string key); // aynı tipteki Deserialize edilmiş dataların bir koleksiyonunu almak için IObservable<IEnumerable<T>> GetAllObjects<T>(); // verilen key listesine karşılık gelen birden çok Deserialize edilmiş datayı almak için. IObservable<IDictionary<string, T>> GetObjects<T>(IEnumerable<string> keys); /* * Store a kayıt eklemek. */ // Tek bir data eklemek için IObservable<Unit> Insert(string key, byte[] data, DateTimeOffset? absoluteExpiration = null); // bir kolejsiyon eklemek için IObservable<Unit> Insert(IDictionary<string, byte[]> keyValuePairs, DateTimeOffset? absoluteExpiration = null); // Otomatik olarak Serialize edilecek bir kompleks objenizi saklamak için. IObservable<Unit> InsertObject<T>(string key, T value, DateTimeOffset? absoluteExpiration = null); // Aynı tipteki kompleks objelerinizi saklamanız için. IObservable<Unit> InsertObjects<T>(IDictionary<string, T> keyValuePairs, DateTimeOffset? absoluteExpiration = null); /* * Store data silmek için. */ // tek bir data silmek için IObservable<Unit> Invalidate(string key); // belli bir liste silmek için IObservable<Unit> Invalidate(IEnumerable<string> keys); // Eğer InserObject ile insert ettiğiniz datalar var ise, aynı şekilde InvalideObject metodu ile silmeniz gerekiyor. IObservable<Unit> InvalidateObject<T>(string key); // aynı şekilde InsertObject edilmiş dataların silinmesi için, tek farkı birden çok datayı silmeniz için bu metod IObservable<Unit> InvalidateObjects<T>(IEnumerable<string> keys); // Object olarak kayıt edilmiş olup olmamasına bakılmaksızın tüm dataların silinmesi için IObservable<Unit> InvalidateAll(); // Belli bir T tipindeki dataların silinmesi için. IObservable<Unit> InvalidateAllObjects<T>(); /* * Saklanan datalar ile ilgili metadata bilgilerini almak için */ // eklenen tüm keyleri dönen metod. IObservable<IEnumerable<string>> GetAllKeys(); // bu key ile saklanmış datanın eklenme tarihini dönen metod. IObservable<DateTimeOffset?> GetCreatedAt(string key); // T tipindeki bir objenin eklendiği tarihi dönen metod. IObservable<DateTimeOffset?> GetObjectCreatedAt<T>(string key); // verilen key lerin oluşturulma tarihlerinin listesini dönen metod. IObservable<IDictionary<string, DateTimeOffset?>> GetCreatedAt(IEnumerable<string> keys); /* * Utility metodları */ // tüm tamamlanmamış operasyonların diske yazıldığından emin olmak için. IObservable<Unit> Flush(); // tüm expire olmuş key ve value larını db den silmek için. IObservable<Unit> Vacuum();
Yukarıdaki tüm metodlar tüm BLobCache tipleri için kullanılabilir. Ama bunlardan daha da kolay olarak işleri çözmemizi sağlayan extension metodlar muhtemelen daha çok tercih edicekleriniz arasında olacaklar.
Bu metodlar aşağıdaki gibi.
/* * Username / Login Metodları (Sadece ISecureBlobCache için) */ // Verilen host için login bilgilerini saklamak. IObservable<Unit> SaveLogin(string user, string password, string host = "default", DateTimeOffset? absoluteExpiration = null); // verilen host taki login bilgilerini okumak. IObservable<LoginInfo> GetLoginAsync(string host = "default"); // verilen host taki bilgileri uçurmak IObservable<Unit> EraseLogin(string host = "default"); /* * url ve imajların download edilip cachelenmesi */ // byte arra olarak download etmek IObservable<byte[]> DownloadUrl(string url, IDictionary<string, string> headers = null, bool fetchAlways = false, DateTimeOffset? absoluteExpiration = null); // download edilen datayı imaj olarak okumak. IObservable<IBitmap> LoadImage(string key, float? desiredWidth = null, float? desiredHeight = null); // Imajı download edip sonrasında imaj olarak geriye dönmek için. IObservable<IBitmap> LoadImageFromUrl(string url, bool fetchAlways = false, float? desiredWidth = null, float? desiredHeight = null, DateTimeOffset? absoluteExpiration = null); /* * Birleşik işlemler */ //Cache deki datayı okumaya çalışır, eğer key i bulamaz ise veya okurken hata //alırsa verdiğini func ı çalıştırır aldığı sonucu aynı key ile cache e atar. IObservable<T> GetOrFetchObject<T>(string key, Func<Task<T>> fetchFunc, DateTimeOffset? absoluteExpiration = null); // GetOrFetchObject gibi sadece async değil. IObservable<T> GetOrCreateObject<T>(string key, Func<T> fetchFunc, DateTimeOffset? absoluteExpiration = null); //GetOrFetchObject gibi ama fark olarak verilen key i db de bulsa bile, o sonucu //hemen döner fakat yine de verdiğiniz func ı çalıştırıp cache deki datayı update eder. IObservable<T> GetAndFetchLatest<T>(this IBlobCache This, string key, Func<IObservable<T>> fetchFunc, Func<DateTimeOffset, bool> fetchPredicate = null, DateTimeOffset? absoluteExpiration = null, bool shouldInvalidateOnError = false, Func<T, bool> cacheValidationPredicate = null)
Bu iki yazımıda okumuş olsanız dahi akavache github reposunu incelemenizi ve Paul Betts in xamarin evolve 2016 da yaptığı konuşmayı izlemenizi öneririm.
Bir sonraki yazımda görüşmek üzere.
Resilient Network Services – Bölüm 5 – Akavache
Selamlar,
Bu yazımda sizlere bu seri kapsamındaki en değerli kütüphanelerden biri olan Akavache den bahsedeceğim.
Akavache async çalışan ve key-value şeklinde data saklamanızı sağlayan, SQLite3 kullanan ve dataları persistant(kalıcı) şekilde tutan bir kütüphane. Desktop ve mobil uygulamalar için eğer lokal veritabanı kullanmak durumunuz var ise biçilmiş kaftan diyebilirim.
Günümüz de neredeyse local storage kullanmayan bir uygulama mevcut değil. Eğer saklamanız gereken dataları da file olarak saklamak gibi bir zorunluluğunuz yok ise kullanacağınız çözüm SQLite olacaktır. Bazı firmalar SQLite üzerinde çalışacak kendi katmanlarını zaten yazmış yada farklı yardımcı kütüphaneler ile ilerliyorlar. Fakat SQLite üzerinde sorgu çalıştırmaki, bilmeden çok fazla hata ve eksik yapmanıza müsait bir durum. En basit örneği verecek olursak, sqlite tarafına attığınız bir sorgu eğer transaction içine alınmadı ise o bunu kendi yapmaya çalışacaktır, bu da sizin sorgunuzun performans kaybetmesi demektir.
Peki hemen öncelikle bu kütüphaneyi nerelerde kullanabiliriz buna bakalım.
Aşağıdaki tüm dotnet platformlarında bu kütüphaneyi kullanabilirsiniz:
- Xamarin.iOS / Xamarin.Mac
- Xamarin.Android
- .NET 4.5 Desktop (WPF)
- Windows Phone 8.1 Universal Apps
- Windows 10 (Universal Windows Platform)
- Tizen 4.0
Akavache yi kullandıktan sonra, zaten hali hazırda kendileri de SQLite kullanmalarına rağmen uygulama performanslarında artış olduğunu söyleyen çok firma var. Peki herkes SQLite kullanmasına rağme bu fark neden oluşuyor?
Sebebi şu; SQLite ın nasıl kullanılmaması gerektiğini bilen kişiler tarafından geliştirildi bu kütüphane, ve yılların birikimi open-source bir proje olarak karşımıza çıktı. Yani eğer “Bende yıllardır kullanıyorum ve hali hazırda yazdığım çok iyi çalışan bir kütüphanem var.” diyor olsanız bile yine de kıyaslama yapmanızı öneririm.
Akavache hem gizlilik değeri olan dataları hemde komplex objeleri (imaj, api response, json data) kolayca cihazda saklamınızı sağlıyor.
Temelinde bir core bir key-value byte array store olarak yazılmış (Dictionary<string, byte[]> gibi düşünebiliriz.) ve bunun üzerine inşa ettikleri çok yardımcı ve kullanımı kolay extension metodları mevcut.
Kullanımına bir bakalım.
Akavache öncelikle BlobCache denen özel bir sınıf ile kullanılıyor diyebiliriz.uygulamanın startup tarafında sadece uyulamanın adını set edeceğiniz tek satır kod ile başlamaya hazır oluyorsunuz.
BlobCache.ApplicationName = “MyApp” veya
Akavache.Registrations.Start(“MyApp”) ve artık hazırsınız.
Cİhazda verilerinizi saklamanız için 4 farklı seçenek mevcut akavache kullanırken.
BlobCache.LocalMachine
– Normal cache lenmiş data. Bu işletim sistemi farklarına göre sizin haberiniz olmadan, işletim sistemi tarafından uçurulmuş olabiliyor. Bunun garantisini vermiyor, veremezde zaten.BlobCache.UserAccount
– User bilgileri. Bazı sistemler bu datayı otomatik olarak cloud ortamlarına yedekleyebiliyor.BlobCache.Secure
– password, iban vb hassas dataları saklamanız için kullanmanız gereken seçenek bu.BlobCache.InMemory
– Adında da anlaşılacağı üzere sadece uygulamanın lifetime ı süresince datayı saklamak için kullanacağınız seçenek de bu olucaktır.
Xamarin.iOS, BlobCache.LocalMachine seçeneği ile saklanmış dataları, diskte yer boşaltmak için silebilir (tabii uygulamanız çalışmıyor ise o an). Ama UserAccount ve Secure seçenekleri ile sakladığınız datalar iCloud ve iTunes da yedeklenecektir.
Xamarin.Android de aynı şekilde LocalMachine üzerinde saklanmış dataları yine diski boşaltmak amaçlı uçurabilir.
Windows 10 (UWP) nin yaptığı bir güzellik ise şu; UserAccount ve Secure tarafında saklanmış dataları cloud a atıyor ve tüm yüklü cihazlar ile senkronize ediyor.
Akavache yi async kullanmak için System.Reactive.Linq api si önemli. async-await bu şekilde çalışır oluyor.
using System.Reactive.Linq; Akavache.Registrations.Start("AkavacheExperiment") var myToaster = new Toaster(); await BlobCache.UserAccount.InsertObject("toaster", myToaster); var toaster = await BlobCache.UserAccount.GetObject<Toaster>("toaster"); Toaster toaster; BlobCache.UserAccount.GetObject<Toaster>("toaster") .Subscribe(x => toaster = x, ex => Console.WriteLine("No Key!"));
Yukarıda görüceğiniz üzere, using olarak System.Reactive.Linq sayesinde aşağıda UserAccount üzerinden GetObject yaparken await işlemi yapabiliyoruz.
Hepsinden önce ilk olarak yukarıda da belirttiğim gibi uygulama adını register ettikten sonra akavache kullanıma hazır hale geliyor.
Async-Await ile kullanmak istemiyorsak, aşağıda yazdığımı gibi Subscribe metodu ile cache aldığımız data üzerinden işlemimizi yapabiliyoruz.
Xamarin Linker Önlemi
Bazılarınız uygulama boyutunu düşürmek için Xamarin Linker ı kullanmıştır. Proje taranıp kullanılmadığı düşünülen dll ler uçurulabilir.
Akavache.Sqlite3 dll inin xamarin build tooları ile projeden uçurulmasını önlemenin(ki bu çok öenmli =) iki yolu var
1). İlk yönetim aşağıdaki gibi, dll deki type ları referance alıcak bir dosya eklemek projeye.
public static class LinkerPreserve { static LinkerPreserve() { var persistentName = typeof(SQLitePersistentBlobCache).FullName; var encryptedName = typeof(SQLiteEncryptedBlobCache).FullName; } }
2) İkinci yöntem ise, ilk belirttiğim gibi;
Sadece uygulamanın adını Akavahce.Registrations.Start metodu ile vermek.
Akavache.Registrations.Start("ApplicationName")
ShutDown
Akavacheyi kullanırken unutmamanız gereken birşey de uygulamanın shut down olayında BlobCache.ShutDown() metodunu çağırmamız. Hatta .Wait() etmemiz. Bunu yapmaz isek, queue ya alınmış datalarımız, önbellekten uçmadan kalabilir.
Bu kadar Akavache dn bahsettikten sonra bir sonraki yazımızda daha detaylı kullanımından ve extension metodlarından bahsedeceğim.
Görüşmek üzere.
Resilient Network Services – Bölüm 4 – ModernHttpClient
Selamlar,
Bu yazımda sizelere ModernHttpClient kütüphanesinden ve uygulamanıza performans olarak katkılarından bahsedeceğim.
ModernHttpClient kullanması belki de en basit kütüphane olabilir 🙂 ama etkileri fazlaca.
Bir xamarin uygulamanızda HttpClient ile beraber yapacağınız requestleri u kütüphane ile yaptığınızda çok hızlı çalıştığını göreceksiniz. Bunun sebebi ise bu kütüphanenin arkada platform spesifik taraflarda kullandığı native kütüphaneler. Bu kütüphaneler şunlar
- iOS için NSURLSession
- Android için OkHttp
Native development yapmış olanlarınız ya bu kütğphaneleri doğrudan kullanmıştır ya da bu kütüphaneleri arkaplanda kullanan başka kütüphaneler kullanmıştır.(AFNetwork gibi)
Bu iki kütüphane hakkında hiçbir fikriniz olmasa bile uygulamanızda bu ikisini kullanıp daha hızlı bir API haberleşmesi için yapmanız gereken sadece şu;
var httpClient = new HttpClient(new NativeMessageHandler());
Xamarin projenizde sadece Portable yada standard projenize ModernHttpClient ı referans ederek bu şekilde kullanıma başlayabilirsiniz.
Kütüphanenin kullanımı kadar kısa ama kendisi kadar faydalı bir yazı olduğunu umarım 🙂
Bir sonraki yazımda görüşmek üzere.