Xamarinモゞュラヌアプリケヌション

この蚘事では、 Notissimusのモゞュラヌアヌキテクチャ䞊に構築されたアプリケヌションの「デザむナヌ」の開発䞭に生じた興味深い問題ずその解決策に぀いお孊びたす。 プロゞェクトは掻発に開発されおいるので、コメントであなたの意芋を知っおうれしく思いたす。たた、Xamarinの開発者向けの2016幎の最終䌚議にも招埅したす。 猫の䞋で興味を持っおいるみんなにお願いしたす。



さらに、ナレヌションは著者に代わっお実斜されたす。


問題の声明


クラむアントは䜕を望んでいたすか


クラむアントは気たぐれな生き物なので、誰もが最終補品アプリケヌションに察しお独自の芁件を持っおいたす。 ただし、䞀般的なりィッシュリストは区別できたす。



これらの4぀のりィッシュリストはクラむアントごずに倉わりたせんが、衚瀺/非衚瀺になる堎合がありたす。 りィッシュリストを決定したら、単玔なプログラマヌにずっおそれらが䜕を意味するかを理解する必芁がありたす。



゜リュヌションスキヌム


タスクを決定したら、次のスキヌムを䜿甚するこずにしたした。


゜リュヌションスキスム


゜リュヌションのアヌキテクチャ


基本モゞュヌル


基本モゞュヌルずは䜕ですか たず、API、コア、UIの3぀の䞻芁な芁玠で構成される䞀皮のアヌキテクチャナニットです。 第二に、新しいモゞュヌルの迅速なアセンブリず接続のためのすべおのベストプラクティスず基本芁玠を含む基本的なベヌスプロゞェクトたずえば、API、LookupService、ラッパヌオヌバヌDB、ベヌスViewModel、UIViewControllersのベヌスクラスなど。 したがっお、各モゞュヌルの基瀎は、基本的なBaseモゞュヌルの1぀たたは耇数の郚分です。


基本モゞュヌルの䟋は次のずおりです。



UI局でこのナビゲヌションを凊理するロゞックは、遞択したナビゲヌションのタむプメニュヌ、タブ、たたはその他に倧きく䟝存し、アプリケヌションぞの゚ントリポむントも䟝存するため、ナビゲヌションモゞュヌルは*を䜿甚したす。 ViewModelを起動したす。これにより、アプリケヌションが起動したす。


トップレベルのモゞュヌル


これらは、プロゞェクトが開発されおいるビゞネスセグメントに䟝存するモゞュヌルです。 それらを個別のレむダヌに分離するこずが決定された理由は明らかですが、私たちはただそれらをリストしおいたす



そのようなモゞュヌルの䟋は次のずおりです。



カタログモゞュヌルからバスケットに商品を远加する必芁があり、バスケットモゞュヌルに盎接リンクせずに远加のラッパヌを䜿甚しおこれを実装するこずは、䟿利な方法ずは蚀えたせん。


プロゞェクトを開始


これは、クラむアントたたは開発者が察話できるプロゞェクトです。 次のものが含たれたす。



䞀般のナヌザヌがこのプロゞェクトでできるこずは、仕様にガむドされおいたす



このプロゞェクトで開発者ができるこず



モゞュヌルのアヌキテクチャ


API


これはポヌタブルクラスラむブラリです。iOSたたはAndroidを問わず、任意のプラットフォヌムで実行できるラむブラリプロゞェクトコヌドです。 暙準APIプロゞェクトには、次のような芁玠が含たれたす。



サヌビスは次のずおりです
public interface IAuthService { /// <summary> ///    e-mail   /// </summary> /// <returns>  </returns> /// <param name="email">E-mail</param> /// <param name="password"></param> Task<string> SignIn(string email, string password); /// <summary> ///    e-mail   .  /// </summary> /// <returns>  </returns> /// <param name="email">E-mail</param> /// <param name="socialTypeName">  . </param> /// <param name="additionalFields"> </param> Task<string> SignInSocial(string email, string socialTypeName, Dictionary<string, object> additionalFields = null); /// <summary> ///    e-mail   /// </summary> /// <returns>  </returns> /// <param name="email">E-mail</param> /// <param name="password"></param> /// <param name="additionalFields"> </param> Task<string> SignUp(string email, string password, Dictionary<string, object> additionalFields = null); /// <summary> ///    /// </summary> /// <returns>  </returns> /// <param name="email">E-mail</param> Task<string> RecoveryPassword(string email); /// <summary> ///   /// </summary> /// <param name="token">  </param> Task SignOut(string token); } public class AuthService : BaseService, IAuthService { #region IAuthService implementation public async Task<string> SignIn(string email, string password) { return await Post<string>(SIGN_IN_URL, ToStringContent(new { email, password })); } public async Task<string> SignInSocial(string email, string socialTypeName, Dictionary<string, object> additionalFields = null) { return await Post<string>(SIGN_IN_SOCIAL_URL, ToStringContent(new { email, socialTypeName, additionalFields })); } public async Task<string> SignUp(string email, string password, Dictionary<string, object> additionalFields = null) { return await Post<string>(SIGN_UP_URL, ToStringContent(new { email, password, additionalFields })); } public async Task<string> RecoveryPassword(string email) { return await Post<string>(RECOVERY_PASSWORD_URL, ToStringContent(new { email })); } public Task SignOut(string token) { return Post(SIGN_OUT_URL, ToStringContent(new { token })); } #endregion } 

プロゞェクトにサヌビスを远加した埌、登録するための远加手順は必芁ありたせん;「レゞストラ」は、次の行のおかげですべお自分で行いたす。


 CreatableTypes() .EndingWith("Service") .AsInterfaces() .RegisterAsLazySingleton(); 

コア


これはPCLプロゞェクトでもあり、MvvmCrossが提䟛する機䌚を䜿甚しお完党に構築されおいたす。 暙準のコアプロゞェクトには、次の芁玠が含たれたす。



 public interface IMenuVmService { public IEnumerable BuildItemsFromJsonConfig(); } public class MenuVmService : IMenuVmService { public IEnumerable BuildItemsFromJsonConfig() { ... } } 


開発を開始する前に、Coreのロゞックのほずんどを再定矩でき、実装ごずに完党に眮き換えるこずができるこずを説明したした。 たた、IoCを介したサヌビスの眮き換えですべおが明らかな堎合、ViewModelsの眮き換えですべおが明らかではありたせん。 「これを実装する方法は」ずいう疑問が生じたした。 答えはViewModelLookupServiceの実装でした。


ViewModelLookupService


これは、ViewModelむンタヌフェヌスを介しお実装を登録できるサヌビスです。 原則はIoCに䌌おおり、VMむンスタンスではViewModelLookupServiceのみが機胜したせん。 ナビゲヌションはどうですか 実際、ShowViewModelVMメ゜ッドは、衚瀺するVMのタむプを取り蟌みたす。 したがっお、ビュヌモデルをサヌビスに登録するず、VMむンタヌフェむスの皮類ずVM実装の皮類に関する完党な情報が取埗され、サヌビスに保存されたす。 登録された実装を取埗するためにサヌビスにアクセスするずき、保存されたデヌタにアクセスし、実装のタむプを返したす。


これにより、configsでモデルの実装を蚭定できたす。 䟋


メニュヌモゞュヌルでリストアむテムを構成する
 ... "items": [ { "icon":"res:Images/Menu/catalog.png", "name":"", "type":"AppRopio.ECommerce.Products.Core.ViewModels.IProductsViewModel", "default":true }, { "icon":"res:Images/Menu/basket.png", "name":"", "type":"AppRopio.ECommerce.Basket.Core.ViewModels.IBasketViewModel", "badge":true }, { "icon":"res:Images/Menu/history.png", "name":" ", "type":"AppRopio.ECommerce.OrdersHistory.Core.ViewModels.IOrdersHistoryViewModel" }, { "icon":"res:Images/Menu/favorites.png", "name":"", "type":"AppRopio.ECommerce.Favorites.Core.ViewModels.IFavoritesViewModel" } ] ... 

したがっお、リストアむテムを蚭定できたす名前、VMタむプ、アむテムをクリックしおナビゲヌションロゞックを呌び出すずきにViewModelLookupServiceから取埗しようずし、アむテムのバッゞを蚭定し、アむテムの1぀を開始画面ずしお指定する必芁がありたす。


ViewModelLookupServiceの導入のおかげでViewModelLookupServiceすべおのVMには独自のむンタヌフェむスがありたす。これにより、UIレむダヌでVMをバむンドするずきにロゞックを眮き換える機胜を倱うこずもなくなりたす。 たた、ViewModelLookupServiceでのViewModelLookupServiceの実装の登録は、各モゞュヌルの前提条件です。


RouterService


実際、 ViewModelLookupServiceを介しおMenuモゞュヌルから移動するのはそれほど簡単でViewModelLookupServiceたせん。 このメカニズムを実装した埌、ナビゲヌションモゞュヌルには、ナビゲヌトされる型ぞの明瀺的なバむンドがなく、メニュヌ項目にナビゲヌトする前にいく぀かのロゞックを実行できるようにする必芁があるず考えたしたたずえば、メニュヌには個人アカりントたたは泚文履歎、ナヌザヌ認蚌の前にブロックする必芁がありたす。 したがっお、RouterServiceメカニズムを開発するこずが決定されたした。


RouterServiceは、VMむンタヌフェむスタむプRouterServiceナビゲヌションを制埡するサヌビスです。 圌の呌びかけは次のずおりです。


 protected void OnItemSelected(IMenuItemVM item) { if (!RouterService.NavigatedTo(item.Type)) MvxTrace.Trace(MvvmCross.Platform.Platform.MvxTraceLevel.Error, "NavigationError: ", $"Can't navigate to ViewModel of type {item.Type}"); } 

任意のタむプのナビゲヌションむベントを凊理するには、モゞュヌルは、このタむプのIRouterSubscriber実装をIRouterSubscriberに登録する必芁がありたす。これには、2぀のメ゜ッドのみが含たれたす。


 public interface IRouterSubscriber { bool CanNavigatedTo(string type); void FailedNavigatedTo(string type); } 

サブスクラむバヌがitem.Type型で登録されおいる堎合、最初のメ゜ッドはRouterService.NavigatedTo(...)メ゜ッド内でRouterService.NavigatedTo(...)れたす。 次に、最初のメ゜ッドがfalseを返した堎合、たたはナビゲヌションの他の段階で゚ラヌが発生した堎合。


最初のメ゜ッドを実装するずき、サブスクラむバヌは自分に来た型を凊理し、必芁なチェックを実行し、合栌した堎合、 ViewModelLookupServiceから登録枈みのモデル実装型を取埗しおナビゲヌトする必芁がありたす。そうでない堎合はfalse必芁がありたす。 FailedNavigatedTo(...)実装する堎合、制限はありたせん。


したがっお、キヌポむントぞのナビゲヌションの凊理はMenuモゞュヌルから取り出され、任意のViewModelsおよび任意のロゞックぞのナビゲヌションが蚱可されたしたたずえば、メニュヌ項目をタップする堎合、画面ではなく䌚瀟のWebサむトでのナビゲヌションが必芁です


UI


レむダヌは、2皮類のプロゞェクトで構成されたす。



各プロゞェクトには必ず次のものが含たれたす。



プラットフォヌムサヌビスの実装に぀いおは、埌ほど説明したす。ナヌザヌむンタヌフェむスの実装は、珟圚実行しおいるものず倉わらないので、アプリケヌションのさたざたなクラむアント蚭定の䜿甚に぀いお詳しく調べたす。


蚭定には次の2぀のタむプがありたす。



蚭定ファむル自䜓は.jsonドキュメントです。 蚭定は、モゞュヌルの起動時に開始される特別なサヌビスに䞀床読み蟌たれたす。 構成蚭定は、ConfigService'yのコア、テヌマ別-ThemeServicesのUIにロヌドされたす。 ファむルからjsonをロヌドする手順はかなり暙準的です。ただし、CoreはPCLです。぀たり、そこにファむルを操䜜するツヌルはありたせん.NET Standard 2.0を参照。 これにより、特別なサヌビスISettingsServiceが導入され、その実装は基本的なBaseモゞュヌルのUIレむダヌにあり、ロゞックが問題なく構成情報をロヌドできるようになりたした。


新しいモゞュヌルを開発し、既存のシステムに接続する段階


新しいモゞュヌルを開発する前に、クラむアントの個人アカりントからアプリケヌションの゜ヌスコヌドを賌入しおダりンロヌドする必芁がありたす。 したがっお、すでに䜜成されたアヌキテクチャず遞択された蚭定を䜿甚しお、2぀の起動されたプロゞェクトiOSおよびAndroid甚を備えた゜リュヌションが埗られたす。 次に、既存のiOSアプリケヌション甚にれロからフォトギャラリヌモゞュヌルを䜜成するこずのみを怜蚎したす。 モゞュヌルは、デバむスのカメラから画像を受信し、サヌバヌに送信し、アルバムに保存しお、コレクションに衚瀺したす。


アヌキテクチャの䜜成


たず、䟿宜䞊、新しい゜リュヌションフォルダヌを䜜成し、フォトギャラリヌず呌びたす。 その埌、3぀のプロゞェクトがこのフォルダヌに远加されたす。



自動的に䜜成されたMyClass.csを削陀し、次のリンクをプロゞェクトに远加したす。



NuGetからMvvmCrossパッケヌゞを各プロゞェクトに接続するこずも必芁です。


APIサヌビスの远加


写真を撮るずき、プラグむンは写真をサヌバヌに送信しお履歎を保存したすたずえば、公開甚。 これを行うには、この䜜業を実行するAPIプロゞェクトにサヌビスを远加したす。 プロゞェクトにServicesフォルダヌを䜜成し、 IPhotoServiceむンタヌフェむスを远加したす。ここで、必芁な機胜を説明したす。


 public interface IPhotoService { Task SendPhoto(byte[] photoData); } 

次に、サヌビスの実装を蚘述したす。


 public class PhotoService : BaseService, IPhotoService { private const string PHOTO_URL = "photo"; #region IPhotoService implementation public async Task SendPhoto(byte[] photoData) { await Post(PHOTO_URL, new ByteArrayContent(photoData)); } #endregion } 

BaseモゞュヌルのBase.APIプロゞェクトにBaseServiceが実装されおいるため、必芁なURLでのク゚リは1行だけで実行されたす。 同様に、サヌバヌから写真を撮る方法の実装を远加できたす。 API゚ントリポむントは、起動されたプロゞェクトの蚭定から取埗され、すべおのリク゚ストのURLプレフィックスずしお䜿甚されたす。 䜕らかの理由でPost...の実装がメ゜ッドに合わない堎合は、ク゚リサヌビスに盎接連絡できたす。


サヌビスを機胜させるには、登録する必芁がありたす。 これを行うには、APIプロゞェクトでAppクラスを䜜成し、次のコヌドを蚘述したす。


 public class App : MvxApplication { public override void Initialize() { CreatableTypes() .EndingWith("Service") .AsInterfaces() .RegisterAsLazySingleton(); } } 

ここでは、 Initializeメ゜ッドで、APIのすべおのサヌビスを、Coreパヌツからの埌続の呌び出しの遅延シングルトヌンずしお自動的に登録したす。


ViewModelずそのサヌビスの䜜成


このモゞュヌルでは、単玔なVMを䜜成したす。このVMには、ナヌザヌから受け取った写真のリストず、新しい写真を远加するボタンのみが含たれたす。 Coreプロゞェクトで、ViewModelsフォルダヌをIPhotogalleryViewModelフォルダヌ内に䜜成し、新しいIPhotogalleryViewModelむンタヌフェむスず新しいIPhotogalleryViewModelクラスを远加しBaseViewModel 。これらは、むンタヌフェむスずBaseViewModelを継承しBaseViewModel 。


IPhotogalleryViewModelむンタヌフェむスに次の行を远加したす。


 ObservableCollection<IPhotoItemVM> Items { get; set; } ICommand AddPhotoCommand { get; } 

アむテム-衚瀺される写真のリスト、AddPhotoCommand-新しい写真をコレクションに远加したす。


すべおの写真ず新しい写真を取埗するためのロゞックのダりンロヌドは、むンタヌフェむスを実装するサヌビスにありたす。


 public interface IPhotogalleryVmService { Task<ObservableCollection<IPhotoItemVM>> LoadItems(); Task<IPhotoItemVM> GetPhotoFromUser(); } 

新しい写真VmService取埗VmServiceために、 VmServiceはデバむスのカメラサヌビスにアクセスし、その実装は各プラットフォヌム䞊にあり、アルバムから写真をアップロヌドするためにアルバムサヌビスにアクセスしたす。


プラットフォヌムサヌビスむンタヌフェむス
 public interface ICameraService { Task<byte[]> TakePhoto(); } public interface IPhotoAlbumService { Task<List<byte[]>> LoadPhotosFrom(string albumName); } 

CoreおよびViewModel'iで利甚可胜なサヌビスを登録するこずのみが残りたすビュヌモデルの登録は、その埌の眮換のために可胜です。 すべおはAPIずの類掚によっお行われたす。App.csが䜜成され、Initializeメ゜ッドが次のように再定矩されたす。


 public override void Initialize() { (new API.App()).Initialize(); CreatableTypes() .EndingWith("Service") .AsInterfaces() .RegisterAsLazySingleton(); var vmLookupService = Mvx.Resolve<IViewModelLookupService>(); vmLookupService.Register<IPhotogalleryViewModel>(typeof(PhotogalleryViewModel)); } 

iOSでのシンプルなレむアりトの開発ずプラットフォヌムサヌビスの実装


たず、すべおのプラットフォヌムサヌビスを実装したす。 カメラサヌビスから始めたしょう。 iOSプロゞェクトにServicesフォルダヌを䜜成し、CameraServiceを远加したす。


 public class CameraService : ICameraService { public Task<byte[]> TakePhoto() { throw new NotImplementedException(); } } 

TakePhotoメ゜ッドの実装
 public async Task<byte[]> TakePhoto() { var mediaFile = await CrossMedia.Current.TakePhotoAsync( new StoreCameraMediaOptions { DefaultCamera = CameraDevice.Rear }); var stream = mediaFile.GetStream(); var bytes = new byte[stream.Length]; await stream.ReadAsync(bytes, 0, (int)stream.Length); PHAssetCollection assetCollection = null; var userCollection = PHAssetCollection.FetchAssetCollections(PHAssetCollectionType.Album, PHAssetCollectionSubtype.Any, null); if (userCollection != null) assetCollection = userCollection.FirstOrDefault(nsObject => (nsObject as PHAssetCollection).LocalizedTitle == ALBUM_NAME) as PHAssetCollection; if (assetCollection == null) { string assetCollectionIdentifier = string.Empty; PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => { var creationRequest = PHAssetCollectionChangeRequest.CreateAssetCollection(ALBUM_NAME); assetCollectionIdentifier = creationRequest.PlaceholderForCreatedAssetCollection.LocalIdentifier; }, (bool success, NSError error) => { assetCollection = PHAssetCollection.FetchAssetCollections(new[] { assetCollectionIdentifier }, null).firstObject as PHAssetCollection; PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => { var assetChangeRequest = PHAssetChangeRequest.FromImage(UIImage.LoadFromData(NSData.FromArray(bytes))); var assetCollectionChangeRequest = PHAssetCollectionChangeRequest.ChangeRequest(assetCollection); assetCollectionChangeRequest.AddAssets(new[] { assetChangeRequest.PlaceholderForCreatedAsset }); }, (bool s, NSError e) => { }); }); } else { PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => { var assetChangeRequest = PHAssetChangeRequest.FromImage(UIImage.LoadFromData(NSData.FromArray(bytes))); var assetCollectionChangeRequest = PHAssetCollectionChangeRequest.ChangeRequest(assetCollection); assetCollectionChangeRequest.AddAssets(new[] { assetChangeRequest.PlaceholderForCreatedAsset }); }, (bool success, NSError error) => { }); } return bytes; } 

フォトアルバムを操䜜するためのサヌビスも远加したす。


 public class PhotoAlbumService : IPhotoAlbumService { public Task<List<byte[]>> LoadPhotosFrom(string albumName) { throw new NotImplementedException(); } } 

LoadPhotosFromメ゜ッドの実装string albumName
 public Task<List<byte[]>> LoadPhotosFrom(string albumName) { var photos = new List<byte[]>(); var tcs = new TaskCompletionSource<List<byte[]>>(); var userCollection = PHAssetCollection.FetchAssetCollections(PHAssetCollectionType.Album, PHAssetCollectionSubtype.Any, null); if (userCollection != null) { var meetUpAssetCollection = userCollection.FirstOrDefault(nsObject => (nsObject as PHAssetCollection).LocalizedTitle == "Xamarin MeetUp") as PHAssetCollection; if (meetUpAssetCollection != null) { var meetUpPhotoResult = PHAsset.FetchAssets(meetUpAssetCollection, null); if (meetUpPhotoResult.Count > 0) meetUpPhotoResult.Enumerate((NSObject element, nuint index, out bool stop) => { var asset = element as PHAsset; PHImageManager.DefaultManager.RequestImageData(asset, null, (data, dataUti, orientation, info) => { var bytes = data.ToArray(); photos.Add(bytes); if (index == (nuint)meetUpPhotoResult.Count - 1) tcs.TrySetResult(photos); }); stop = index == (nuint)meetUpPhotoResult.Count; }); else return new Task<List<byte[]>>(() => photos); } } else return new Task<List<byte[]>>(() => photos); return tcs.Task; } 

NSCameraUsageDescriptionおよびNSPhotoLibraryUsageDescriptionキヌをInfo.plistに远加するこずを忘れないでください。


画面を構成するには、Viewフォルダヌをプロゞェクトに远加し、その䞭にPhotogalleryフォルダヌを䜜成しお、PhotogalleryViewControllerを远加PhotogalleryViewController 。 UICollectionViewのInterface Builderに2぀の芁玠、 UICollectionViewずUIButtonを_addPhotoBtnそれぞれ_photoCollectionず_addPhotoBtnのアりトレットを䜜成しUIButton 。 次に、 BindControlsメ゜ッドでそれらをバむンドしたす。


 protected override void BindControls() { _photoCollection.RegisterNibForCell(PhotogalleryCell.Nib, PhotogalleryCell.Key); var dataSource = new MvxCollectionViewSource(_photoCollection, PhotogalleryCell.Key); var set = this.CreateBindingSet<PhotogalleryViewController, IPhotogalleryViewModel>(); set.Bind(dataSource).To(vm => vm.Items); set.Bind(_addPhotoBtn).To(vm => vm.AddPhotoCommand); set.Apply(); _photoCollection.DataSource = dataSource; _photoCollection.ReloadData(); } 

これで、モゞュヌルは完党に䜜業できる状態になりたした。メむンプロゞェクトに接続するだけです。


新しいモゞュヌルをメむンプロゞェクトに接続する


モゞュヌルを接続するには、6぀の手順を実行する必芁がありたす。


最初のもの 。 PluginLoaderクラスをCoreプロゞェクトに远加したす。これにより、App.csの初期化が開始されたす。


プラグむンロヌダヌ
 public class PluginLoader : IMvxPluginLoader { public static readonly PluginLoader Instance = new PluginLoader(); private bool _loaded; public void EnsureLoaded() { if (_loaded) return; new App().Initialize(); var manager = Mvx.Resolve<IMvxPluginManager>(); manager.EnsurePlatformAdaptionLoaded<PluginLoader>(); MvxTrace.Trace("Auth plugin is loaded"); _loaded = true; } } 

二番目 。 ViewControllerおよびプラットフォヌムサヌビスが登録されるUIプロゞェクトにプラグむンクラスを远加したす。


プラグむン
 public class Plugin : IMvxPlugin { public void Load() { var viewLookupService = Mvx.Resolve<IViewLookupService>(); viewLookupService.Register<IPhotogalleryViewModel, PhotogalleryViewController>(); Mvx.RegisterSingleton<ICameraService>(() => new CameraService()); Mvx.RegisterSingleton<IPhotoAlbumService>(() => new PhotoAlbumService()); } } 

第䞉 。 クラスXMU_PhotogalleryPluginBootstrapを起動したプロゞェクトに远加したす。


XMU_PhotogalleryPluginBootstrap
 public class XMU_PhotogalleryPluginBootstrap : MvxLoaderPluginBootstrapAction<PluginLoader, Photogallery.iOS.Plugin> { } 

4番目 。 構成のメニュヌからフォトギャラリヌぞのナビゲヌションを指定したす。


フォトギャラリヌナビゲヌション
 { "icon":"res:Images/Menu/photo.png", "name":"", "type":"Photogallery.Core.ViewModels.Photogallery.IPhotogalleryViewModel" } 

5番目 。 ナビゲヌションむベント凊理をCoreプラグむンに远加したす。


フォトギャラリヌRouterSubscriber
 public class PhotogalleryRouterSubscriber : MvxNavigatingObject, IRouterSubscriber { private string VM_TYPE = (typeof(IPhotogalleryViewModel)).FullName; public override bool CanNavigatedTo(string type) { return type == VM_TYPE ? ShowViewModel(LookupService.Resolve(type)) : false; } public override void FailedNavigatedTo(string type) { //nothing } } 

6番目 。 それをApp.csに登録したす。


登録PhotogalleryRouterSubscriber
 var routerService = Mvx.Resolve<IRouterService>(); routerService.Register<IPhotogalleryViewModel>(new PhotogalleryRouterSubscriber()); 

プロゞェクトを実行し、すべおが蚈画どおりに機胜するこずを確認したす。


おわりに


プラットフォヌムで䜜業する際の䞻なポむントを調べたした。 私が䌝えたかった䞻な考え



読曞䞭に珟れた思考の議論をコメントに移すこずをお勧めしたす。 読んでくれおありがずう


著者に぀いお


Maxim Evtukh -NOTISSIMUS瀟のXamarinフレヌムワヌクでのモバむルアプリケヌションの開発者。 2013幎以降のモバむル開発。 空き時間に、圌女はMvvmCrossを改善し、新しいマテリアルデザむンガむドを実装するためのGitHubコントロヌルをサポヌトする問題を研究しおいたす。


Denis Kretov-NOTISSIMUSのテクニカルディレクタヌ。 圌は、iBeaconに基づいた゜リュヌションだけでなく、オンラむンストア向けのモバむルアプリケヌションの開発を専門ずしおいたす。


Xamarinブログのその他の蚘事に぀いおは、# xamarincolumnをご芧ください。



Source: https://habr.com/ru/post/J316714/


All Articles