Xamarin でセッションデータを保存・復元したい 【Windows RT 編】
Xamarin.Forms に Windows ストアアプリと Windows Phone 8.1 がついにやってきた!
Windows Phone 8.0 などなかったのだ、いいね?
ということで Windows ランタイムアプリ用のセッションデータ保存も Xamarin から試してみます
Xamarin 用の Windows ストアアプリや Windows Phone 8.1 アプリプロジェクトの追加の仕方はきっと、某イケメンさん がわかりやすくまとめてくれると思うのですっ飛ばします!
スポンサードリンク
追加するのは他のプラットフォームと同じく XmlRepository.cs
/// <summary> /// XML リポジトリ /// </summary> public class XmlRepositories : ISessionRepository { /// <summary> /// 保存先フォルダ /// </summary> private static readonly StorageFolder Folder = ApplicationData.Current.LocalFolder; /// <summary> /// データストア /// </summary> private Dictionary<Type, object> storage = new Dictionary<Type, object>(); /// <summary> /// コンストラクタ /// </summary> static XmlRepositories() { } /// <summary> /// データを設定します /// </summary> /// <typeparam name="T">データの型</typeparam> /// <param name="value">データ</param> public void SetValue<T>(T value) where T : class { this.storage[typeof(T)] = value; } /// <summary> /// データを取得します /// </summary> /// <typeparam name="T">データの型</typeparam> /// <returns>データ</returns> public T GetValue<T>() where T : class { if (!this.storage.ContainsKey(typeof(T))) { return null; } return this.storage[typeof(T)] as T; } /// <summary> /// 初期化します /// </summary> /// <returns>成功した場合<code>true</code>、それ以外は<code>false</code></returns> public bool Initilize() { try { this.storage.Clear(); return true; } catch (Exception) { return false; } } /// <summary> /// セッションデータを読み込みます /// </summary> /// <returns>成功した場合<code>true</code>、それ以外は<code>false</code></returns> public async Task<bool> LoadAsync() { var result = true; try { var types = new List<string>(); var indexFile = await Folder.GetFileAsync("session-keys.xml"); using (var stream = await indexFile.OpenSequentialReadAsync()) { var serializer = new XmlSerializer(types.GetType()); types = serializer.Deserialize(stream.AsStreamForRead()) as List<string>; } foreach (var typename in types) { this.storage[Type.GetType(typename)] = null; } } catch (Exception) { } foreach (var data in this.storage.ToList()) { try { var file = await Folder.GetFileAsync(string.Format("{0}.xml", data.Key.Name)); using (var stream = await file.OpenSequentialReadAsync()) { var serializer = new XmlSerializer(data.Key); this.storage[data.Key] = serializer.Deserialize(stream.AsStreamForRead()); } } catch (FileNotFoundException) { this.storage[data.Key] = null; continue; } catch (InvalidOperationException) { this.storage[data.Key] = null; continue; } catch (Exception) { result = false; } } return result; } /// <summary> /// セッションデータを保存します /// </summary> /// <returns>成功した場合<code>true</code>、それ以外は<code>false</code></returns> public async Task<bool> SaveAsync() { var result = true; try { var types = (from t in this.storage select t.Key.AssemblyQualifiedName).ToList(); var indexFile = await Folder.CreateFileAsync("session-keys.xml", CreationCollisionOption.ReplaceExisting); using (var stream = await indexFile.OpenStreamForWriteAsync()) { var serializer = new XmlSerializer(types.GetType()); serializer.Serialize(stream, types); } } catch (Exception) { } foreach (var data in this.storage) { try { var file = await Folder.CreateFileAsync(string.Format("{0}.xml", data.Key.Name), CreationCollisionOption.ReplaceExisting); using (var stream = await file.OpenStreamForWriteAsync()) { var serializer = new XmlSerializer(data.Key); serializer.Serialize(stream, data.Value); } } catch (FileNotFoundException) { continue; } catch (InvalidOperationException) { continue; } catch (Exception) { result = false; } } return result; } }
Windows Phone 8.0 のときとそれほど変わらないですね
Windows ストアアプリと Windows Phone 8.1 は API がかなり統一されているので、iOS と Android の場合と同じくファイルリンクで共通化できちゃいます
とりあえず下記の手順で動作確認
- アプリ起動
- ホームボタンでバックグラウンド遷移
- 戻るボタンで再開
- Visual Studio から中断とシャットダウン
- Visual Studio から再度起動
あ・・・あれ?!復元できてませんね
ログを見てみると・・・
TopPage.xaml.OnAppearing: TopPage Appearing. App.OnSleep: sleeped.
あちゃ~ Xamarin.Forms App Lifecycle はまだ Windows ランタイムアプリに完全対応してないみたいですね
中断とシャットダウンのときだけ OnSleep が呼ばれる謎仕様・・・むむむぅ