2017-04-19 2 views
4

Xamarin Forms 응용 프로그램에서 객체를 삭제하는 올바른 방법을 찾고 있습니다. 현재 XAML 및 MVVM 코딩 스타일을 사용하고 있습니다. 그런 다음 내보기 모델에서 나는 기본 서비스 로케이터 (DependencyService)를 통해 일회용 객체에 대한 참조를 얻습니다. 이상 적으로 내보기 모델에서 개체에 Dispose()를 호출 할 수 있어야하지만 ContentPage.OnDisappearingNavigationPage.Popped에 연결하는 것과 같은 다른 솔루션이 가능할 수 있습니다.Xamarin.Forms에서 객체 삭제

+0

당신이 묻는 질문은 확실하지 않습니다. 이미 작성한 제안에 무엇이 잘못 되었습니까? – Neil

+0

뷰 모델에서 처리 방법을 어떻게 처리해야할지 모르겠다. 다른 두 가지 옵션은 코드가 다른 파일에 분산되어 있고 추가 코딩이 필요하므로 깔끔하지 않습니다. – Kalitsov

답변

2

2 주 전 거의 같은 요구 사항이있었습니다. 내 뷰 모델의 이벤트 구독이 페이지가 닫힐 때 구독 취소되는지 확인하려고했습니다. 많은 연구 끝에 내 결론은 가장 간단한 해결책은 ContentPage.OnDisappearing 메서드를 사용하는 것이 었습니다.

처분하려는 객체가 ViewModel에 있음을 지적 했으므로 ViewModel에 사라진 시점을 알려주는 인프라가 필요합니다. 이를 위해 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 메소드를 오버라이드 (override)하고 개체를 처리 할 수 ​​있습니다 :

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

     // Dispose whatever objects are neede here 
    } 
} 
당신이 페이지를 구현할 때

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의 있는지 확인

주의해야 할 점은 스택 탐색을 사용하는 경우 OnDisappearing 메서드는 현재 페이지의 다른 페이지를 스택 할 때 호출됩니다 (페이지가 사라지는 템포 어쨌든 결국). 따라서이 문제를 해결해야하고 아마도이 경우에 객체를 처리하지 않아야합니다. 그러나 페이지 상단에 아무것도 쌓지 않으면 걱정할 것이 없습니다. 제 경우에는 단지 이벤트 구독 이었기 때문에 OnAppearing에 이벤트 핸들러를 첨부하고 OnDisappearing에서 이벤트 핸들러를 분리했습니다.

나는 당신을 돕기를 바랍니다.

2

ListViews 또는 Labels에 대한 바인딩이 페이지/조각이 삭제 될 때 값이 변경되면 양식에 개체 예외가 처리됩니다. 나는 당신이 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에서는 작동 할 것이라고 생각합니다. 그러나 그 당시 우리 게임은 팝/제거되었을 때조차도 메모리에 보관중인 조각, 페이지 및 팝업 안에 정말 복잡한 ListView가있었습니다 우리는 바인딩과 ItemsSource를 지울 때까지 스택에서 가져온 것이 아니며 gc가 아니 었습니다. – Nick