2017-04-19 17 views
4

私はXamarin Formsアプリケーションでオブジェクトを処分する正しい方法を探しています。現在、私はXAMLとMVVMコーディングスタイルを使用しています。私のビューモデルから、私は組み込みサービスロケータ(DependencyService)を介して使い捨てオブジェクトへの参照を取得します。理想的には、ビューモデルからオブジェクトにDispose()を呼び出すことができるはずですが、ContentPage.OnDisappearingNavigationPage.Poppedに接続するなどの他のソリューションも実現可能です。Xamarin.Formsでオブジェクトを廃棄する

+0

あなたは何を質問しているのですか。あなたがすでに提案した提案に何が間違っていますか? – Neil

+0

私はビューモデルからの処分をどのように処理すべきか分かりません。他の2つのオプションは、コードが異なるファイルにまたがって広がっており、追加のコーディングが必要なため、きれいではありません。 – Kalitsov

答えて

2

私は数週間前にほとんど同じ要件を持っていました。私は、ページが閉じられたときに、自分のビューモデルのイベントサブスクリプションの購読を解除するようにしたいと思っていました。多くの研究の後、私の結論は、最も簡単な解決策はContentPage.OnDisappearingメソッドを使用することでした。

あなたが処理したいオブジェクトがViewModelにあることを指摘したので、それが消えているときにViewModelに通知するためのインフラストラクチャが少し必要です。これを行うために、2つの主要なメソッドOnAppearingとOnDisappearingを持つビューモデルの基本実装を定義しました(ここではIPropertyNotify実装などの他の基本機能があるため、インターフェイスではなくクラスです)。

public class ViewModelBase 
{ 
    /// <summary> 
    /// Called when page is appearing. 
    /// </summary> 
    public virtual void OnAppearing() 
    { 
     // No default implementation. 
    } 

    /// <summary> 
    /// Called when the view model is disappearing. View Model clean-up should be performed here. 
    /// </summary> 
    public virtual void OnDisappearing() 
    { 
     // No default implementation. 
    } 
} 

は、その後、私はContentPageをsubsclassedとOnAppearingとOnDisappearingメソッドをオーバーライドして、私の見解モデルを通知するためにそれらを使用しています。

<?xml version="1.0" encoding="utf-8" ?> 
<pages:PageBase xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      xmlns:controls="clr-namespace:Forms.App.Controls;assembly=Forms.App" 
      xmlns:converters="clr-namespace:Forms.App.Converters;assembly=Forms.App" 
      xmlns:pages="clr-namespace:Forms.App.Pages;assembly=Forms.App" 
      x:Class="Forms.App.Pages.LogonPage" 
      NavigationPage.HasNavigationBar="False" 
      Title="Logon"> 

そして、あなたのViewModelにあなたは、あなたのOnDisappearingメソッドをオーバーライドして、オブジェクトを配置することができます:あなたがページを実装する際

public class PageBase : ContentPage 
{ 
    /// <summary> 
    /// Performs page clean-up. 
    /// </summary> 
    protected override void OnDisappearing() 
    { 
     base.OnDisappearing(); 

     var viewModel = BindingContext as ViewModelBase; 

     // Inform the view model that it is disappearing so that it can remove event handlers 
     // and perform any other clean-up required.. 
     viewModel?.OnDisappearing(); 
    } 

    protected override void OnAppearing() 
    { 
     // Inform the view model that it is appearing 
     var viewModel = BindingContext as ViewModelBase; 

     // Inform the view model that it is appearing. 
     viewModel?.OnAppearing(); 
    } 
} 

それからちょうどそれが型PageBaseであることを確認してください

public class FormViewModel : ViewModelBase 
{ 
    public override void OnDisappearing() 
    { 
     base.OnDisappearing(); 

     // Dispose whatever objects are neede here 
    } 
} 

スタックナビゲーションを使用している場合、現在のページの上に別のページをスタックすると、OnDisappearingメソッドが呼び出されます(ページが消えているテンポやがて結局のところ)。だからあなたはこれに対応し、おそらくあなたのオブジェクトを処分しないでください。しかし、あなたのページの上に何かを積み重ねていなければ、心配することはありません。私のケースでは、イベントのサブスクリプションだけだったので、OnAppearingにイベントハンドラを添付し、OnDisappearingでイベントハンドラを切り離しました。

私はあなたを助けることを願っています!

2

ListViewsまたはLabelsへのバインディングがページ/フラグメントが破棄されているときに値が変更されたときに、Formsにオブジェクト例外が処理されていました。あなたがViewModel内のオブジェクトを、私たちがバインディングを削除していたのと同じ場所に配置できると仮定しています。

protected override void OnParentSet() 
{ 
    base.OnParentSet(); 

    if (Parent == null) 
    { 
     //Clear a bunch of bindings or dispose of ViewModel objects 
     BindingContext = 
      _listView.ItemsSource = null; 
    } 
} 
+0

これはカスタムコントロールにも使用できます。どうも! – Marek

+0

は、_listview = nullを設定する方が良いわけではありません。 – batmaci

+0

私が試した最初のことだったと思います。新しいバージョンのFormsではうまくいくかもしれませんが、この時点では、ポップ/削除してもメモリに保持されていたフラグメント、ページ、ポップアップの中に、スタックから削除され、バインディングとItemsSourceをクリアするまではgcではありませんでした。 – Nick

関連する問題