Xamarinアプリケーション用の便利なREST

Xamarin開発者は、ネットワークを操作するためのさまざまなコンポーネントにアクセスできます。本日の記事では、Xamarin.FormsのPCLプロジェクトでも使用できるモジュールのセットを取り上げます。



列のすべての記事は、リンク#xamarincolumnで 、またはカットの下の資料の最後で見つけて読むことができます。







REST APIクライアントの便利な説明を追加



サーバーとモバイルアプリケーションを通信するための最も一般的なプロトコルは、Jsonと組み合わせたRESTです。 したがって、今日はRefitライブラリで知り合いを始めます。



Refitを使用すると、RESTサービスを操作するための仕様を、個々のリクエストのHTTPヘッダーを操作する機能など、入力および出力パラメーターの明確なセットを備えたシンプルなインターフェイスの形式で記述できます。 たとえば、 httpbin.orgサービスのデモAPIを使用します。



[Headers("Accept: application/json")] public interface IHttpbinApi { [Get("/basic-auth/{username}/{password}")] Task<AuthResult> BasicAuth(string username, string password, [Header("Authorization")] string authToken, CancellationToken ctx); [Get("/cache")] Task<HttpResponseMessage> CheckIfModified([Header("If-Modified-Since")] string lastUpdateAtString, CancellationToken ctx); [Post("/post")] Task<HttpResponseMessage> FormPost([Body(BodySerializationMethod.UrlEncoded)] FormData data, CancellationToken ctx); }
      
      





このインターフェースの説明の後、Refitの入力に送られます。



  var client = new HttpClient(new NativeMessageHandler()) { BaseAddress = new Uri("http://httpbin.org") }; _httpbinApiService = RestService.For<IHttpbinApi>(client);
      
      





データ自体は、必要に応じて(キャメルケースまたはスネークアイの変換、セットから文字列値への変換)、Refitで使用されるため、 Json.netライブラリの属性を使用して拡張できます。



  public class AuthResult { [JsonProperty("authenticated")] public bool IsAuthenticated { get; set; } [JsonProperty("user")] public string Login { get; set; } }
      
      





Refitでは、変換済みのDTOまたはHttpResponseMessageオブジェクトを出力値として取得できます。 後者を使用すると、リクエストとレスポンスに関する情報を取得できます。これはデバッグ時に役立ちます。 オプションで、ModernHttpClientを使用してHttpClientを作成することもできます。 一般に、RefitはXamarin開発者にとっても非常に便利で普遍的なツールです。



注1: Xamarin.Forms PCLプロジェクトにRefit 3.0をインストールするには、プロジェクトを.NET Standardに切り替える必要があります



注2: Refitのドキュメントでは、CancelationTokenを使用してアクティブな操作をキャンセルすることについては言及されていませんが、このメカニズムは機能し、 チケットで説明されています。



ポリー



モバイルアプリケーションを開発する場合、多くの場合、セルラーネットワークの信号不安定性の要因を考慮する必要があります。したがって、ネットワーク要求を実行するときには、繰り返し試行することが必要になることがよくあります。 これにより、ユーザーに再度気を散らせずに、リクエストを繰り返すように求めることができます。



Refit and Pollyを使用する興味深いアプローチ 、彼のブログで Rob Gibbensによって説明されました( Fusilladeを使用してネットワーク要求に優先順位を付けることによって、追加の例を示します)。



これがリクエストの作成方法です。



 protected async Task<RequestResult> MakeRequest<T>(Func<CancellationToken, Task<T>> loadingFunction, CancellationToken cancellationToken) { Exception exception = null; var result = default(T); try { result = await Policy.Handle<WebException>().Or<HttpRequestException>() .WaitAndRetryAsync(3, i => TimeSpan.FromMilliseconds(300), (ex, span) => exception = ex) .ExecuteAsync(loadingFunction, cancellationToken); } catch (Exception e) { //      -    DNS exception = e; } //TODO:       return result; }
      
      





loadingFunctionの代わりに、Refit呼び出しコードを渡す必要があります。



  var authToken = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}")); return await MakeRequest(ct => _httpbinApiService.BasicAuth(username, password, authToken, ct), cancellationToken);
      
      





そこで、Refit、Polly、ModernHttpClientを統合しました。



キャッシュ



また、記事の最後で、ネットワークを操作するときにキャッシュの使用を検討できます。 Xamarin開発者はターゲットプラットフォームのすべての機能にアクセスできるため、さまざまなDBMSを使用してキャッシュを実装できます。 最も人気のあるキャッシュの1つは、 SQLiteの上で実行されるAkavacheです。



  var cache = BlobCache.LocalMachine; var cachedObjects = cache.GetAndFetchLatest("objects", GetRemoteObjectAsync, offset => { TimeSpan elapsed = DateTimeOffset.Now - offset; return elapsed > new TimeSpan(hours: 0, minutes: 30, seconds: 0); });
      
      





非常に便利なモバイルレルム DBMSを使用してキャッシュを実装することもできます。 以下は、レルムに基づいたキャッシュの例です。



  public static class LocalCache { private class CachedObject : RealmObject { [PrimaryKey] public string Key { get; set; } public string Value { get; set; } public DateTimeOffset UpdatedAt { get; set; } } private static readonly RealmConfiguration Configuration = new RealmConfiguration("cache.realm", true); private static Realm Db => Realm.GetInstance(Configuration); public static async Task WriteToCache<T>(string key, T data, DateTimeOffset timeStamp) { if (String.IsNullOrEmpty(key) || data == null || timeStamp == DateTimeOffset.MinValue) return; var currentValue = Db.All<CachedObject>().Where(o => o.Key == key).ToList().FirstOrDefault(); if (currentValue == null) await Db.WriteAsync(db => { var newValue = db.CreateObject<CachedObject>(); newValue.Key = key; newValue.UpdatedAt = timeStamp; newValue.Value = JsonConvert.SerializeObject(data); }); else using (var transaction = Db.BeginWrite()) { currentValue.Value = JsonConvert.SerializeObject(data); currentValue.UpdatedAt = timeStamp; transaction.Commit(); } } public static DateTimeOffset CacheLastUpdated(string key) { if (String.IsNullOrEmpty(key)) return DateTimeOffset.MinValue; var currentValue = Db.All<CachedObject>().Where(o => o.Key == key).ToList().FirstOrDefault(); return currentValue?.UpdatedAt ?? DateTimeOffset.MinValue; } public static void RemoveCache(string key) { if (String.IsNullOrEmpty(key)) return; var currentValue = Db.All<CachedObject>().Where(o => o.Key == key).ToList().FirstOrDefault(); if (currentValue == null) return; using (var transaction = Db.BeginWrite()) { Db.Remove(currentValue); transaction.Commit(); } } public static T GetFromCache<T>(string key) { if (String.IsNullOrEmpty(key)) return default(T); var currentValue = Db.All<CachedObject>().Where(o => o.Key == key).ToList().FirstOrDefault(); return currentValue?.Value == null ? default(T) : JsonConvert.DeserializeObject<T>(currentValue.Value); } public static void ClearCache() { Realm.DeleteRealm(Configuration); } }
      
      





おわりに



そこで、今日は、REST APIと統合するときにRefitJson.netModernHttpClientPolly、およびRealmを使用することを検討しました。 次の記事では、Xamarinと外部サービスおよびAzureとの統合について検討します。



著者について





ヴャチェスラフ・チェルニコフ -開発部長、 ビンウェル 過去には、Nokia ChampionおよびQt認定スペシャリストの1人であり、現在はXamarinおよびAzureプラットフォームのスペシャリストです。 彼は2005年にモバイル分野に参入し、2008年からモバイルアプリケーションを開発しています。Symbian、Maemo、Meego、Windows Mobileから始め、その後iOS、Android、Windows Phoneに切り替えました。



著者の他の記事:





便利なリンク






All Articles