MvvmCross が画面遷移回りで Parcelable をどうしているのかのぞいてみた
JXUGC #13の記事に @amay077 さんからコメントを頂いたのでそれに関して MvvmCross を少しのぞいてみました.
以下いただいたコメントです.
Parcelable を JSON 文字列で代替する手法は今回の要件では問題になりませんでしたが、一般的なアプリ開発では好ましくないと思われるでしょう。その点はご注意ください。MvvmCross はこの問題をうまくクリアしているようなので、コードを読まれると良いかもしれません。
MvvmCross は Parcelable を上手くやってるようです.
MvvmCross の画面遷移
Build INSIDER の MvvmCrossの画面遷移に関する記事です.
どうやら中身の実装は MvxAndroidViewPresenter クラスにあるようです.
public virtual void Show(MvxViewModelRequest request)
{
var intent = CreateIntentForRequest(request);
Show(intent);
}
protected virtual void Show(Intent intent)
{
var activity = Activity;
if (activity == null)
{
MvxTrace.Warning("Cannot Resolve current top activity");
return;
}
activity.StartActivity(intent);
}
protected virtual Intent CreateIntentForRequest(MvxViewModelRequest request)
{
var requestTranslator = Mvx.Resolve();
var intent = requestTranslator.GetIntentFor(request);
return intent;
}
MvxViewModelRequest から Intent を生成している流れが今回の話題のコアっぽいです.
IMvxAndroidViewModelRequestTranslator の実装部である MvxAndroidViewsContainer について更に見ていきます.
public virtual Intent GetIntentFor(MvxViewModelRequest request)
{
var viewType = GetViewType(request.ViewModelType);
if (viewType == null)
{
throw new MvxException("View Type not found for " + request.ViewModelType);
}
var converter = Mvx.Resolve();
var requestText = converter.Serializer.SerializeObject(request);
var intent = new Intent(this._applicationContext, viewType);
intent.PutExtra(ExtrasKey, requestText);
this.AdjustIntentForPresentation(intent, request);
return intent;
}
MvxViewsContainer の #GetViewType です.
public Type GetViewType(Type viewModelType)
{
Type binding;
if (this._bindingMap.TryGetValue(viewModelType, out binding))
{
return binding;
}
foreach (var viewFinder in this._secondaryViewFinders)
{
binding = viewFinder.GetViewType(viewModelType);
if (binding != null)
{
return binding;
}
}
if (this._lastResortViewFinder != null)
{
binding = this._lastResortViewFinder.GetViewType(viewModelType);
if (binding != null)
{
return binding;
}
}
throw new KeyNotFoundException("Could not find view for " + viewModelType);
}
Bindingまわりをどうこうしてるくらいの解釈でいいはず…
問題の箇所は以下の部分ですね.
var converter = Mvx.Resolve();
var requestText = converter.Serializer.SerializeObject(request);
IMvxNavigationSerializer とそのメンバ変数である IMvxTextSerializer を更に見ていきます.
namespace MvvmCross.Core.ViewModels
{
using MvvmCross.Platform.Platform;
public interface IMvxNavigationSerializer
{
IMvxTextSerializer Serializer { get; }
}
}
namespace MvvmCross.Platform.Platform
{
using System;
public interface IMvxTextSerializer
{
T DeserializeObject(string inputText);
string SerializeObject(object toSerialise);
object DeserializeObject(Type type, string inputText);
}
}
IMvxTextSerializer の実装部である MvxViewModelRequestCustomTextSerializer のメソッドが以下になります.
public string SerializeObject(object toSerialise)
{
if (toSerialise is MvxViewModelRequest)
return this.Serialize((MvxViewModelRequest)toSerialise);
if (toSerialise is IDictionary)
return this.Serialize((IDictionary)toSerialise);
throw new MvxException("This serializer only knows about MvxViewModelRequest and IDictionary");
}
protected virtual string Serialize(MvxViewModelRequest toSerialise)
{
var stringDictionaryWriter = new MvxStringDictionaryWriter();
var dictionary = new Dictionary();
dictionary["Type"] = this.SerializeViewModelName(toSerialise.ViewModelType);
var requestedBy = toSerialise.RequestedBy ?? new MvxRequestedBy();
dictionary["By"] = ((int)requestedBy.Type).ToString();
dictionary["Info"] = requestedBy.AdditionalInfo;
dictionary["Params"] = stringDictionaryWriter.Write(toSerialise.ParameterValues);
dictionary["Pres"] = stringDictionaryWriter.Write(toSerialise.PresentationValues);
return stringDictionaryWriter.Write(dictionary);
}
返り値を実際に返している MvxStringDictionaryWriter のメソッドが以下になります.
public string Write(IDictionary dictionary)
{
if (dictionary == null
|| dictionary.Count == 0)
{
return string.Empty;
}
var output = new StringBuilder();
foreach (var kvp in dictionary)
{
if (output.Length > 0)
output.Append(";");
output.AppendFormat("{0}={1}", this.Quote(kvp.Key), this.Quote(kvp.Value));
}
return output.ToString();
}
基本的に String で返していますね.
Key-Value の構造も特殊なわけでもなさそうなので、工夫のポイントは MvxViewModelRequest にあるのかな?
一通り流れを追ったところで今回はここまでにします.
次回に続きます(たぶん).
ディスカッション
コメント一覧
まだ、コメントがありません