2014-01-07 1 views
2

MVVMcross 뷰의 수는 원격 서비스에 따라 달라 지므로 완전히 표시됩니다. 우리는 일반적으로 ViewModel의 Init()에서 Task를 비동기로 가져 오기 위해 Task를 해제합니다. ViewModel 속성은 완료시 Task에 설정되고 UI는 PropertyChanged 알림을 통해 업데이트됩니다.뷰 바인딩 설정이 완료 될 때까지 PropertyChanged 이벤트를 연기하십시오.

때때로 원격 데이터 (및 작업)가보기가 해당 수신기를 바인딩하기 전에 완료되어 속성 변경 이벤트가 수신되지 않는 경우가 있습니다.

이 문제는 async Init and Property Changed in MvvmCross에서 다루어졌지만 해결책은 프리젠 테이션 논리의 중복과 같은 느낌입니다.

ViewDidLoad가 끝날 때까지 PropertyChanged 알림을 버퍼링하는 데 성공했지만, 아래에서 MVX 프레임 워크에 연결하여보다 일반적인 솔루션으로 바꾸고 싶습니다.

viewDidLoad가 완료된 후 mvvmcross의 뷰 생성을 후크하여 코드를 실행 중지 할 수 있습니까?

자료보기 모델

public abstract class BaseViewModel : MvxViewModel{ 
     protected bool _deferPropertyChangedEvents = true; 
     private readonly List<PropertyChangedEventArgs> _deferedPropertyChangedEvents = new List<PropertyChangedEventArgs>(); 

     public override void RaisePropertyChanged(PropertyChangedEventArgs changedArgs) 
     { 
      lock(_deferedPropertyChangedEvents){ 
       if (!_deferPropertyChangedEvents) 
       { 
        base.RaisePropertyChanged(changedArgs); 
       } 
       else 
       { 
        // buffer it up 
        _deferedPropertyChangedEvents.Add(changedArgs); 
       } 
      } 
     } 

     public void EndDeferringPropertyChangedEvents() 
     { 
      lock(_deferedPropertyChangedEvents){  
       _deferPropertyChangedEvents = false; 

       // playback all buffered notifications 
       foreach (var e in _deferedPropertyChangedEvents) 
       { 
        RaisePropertyChanged(e); 
       } 

       _deferedPropertyChangedEvents.Clear(); 
      } 
     } 
} 

간단한 대답으로
public class SomeView : MvxViewController 
    { 
     public override void ViewDidLoad() 
     { 
      base.ViewDidLoad(); 

      var bindings = this.CreateBindingSet<StopView, SomeViewModel>(); 
      ..... 
      bindings.Apply(); 

      // plays back any PropertyChanged() notifications that were buffered 
      // up while the view was initializing 
      // ---> want to find a way to have MVX call this 
      ViewModel.EndDeferringPropertyChangedEvents(); 
     } 
    } 

답변

1

, 나는 당신의 자신의 라인이 쉽게 BaseViewModel 캐스트 사용하여 호출 할 수 있다고 생각 샘플보기 :

 // ---> want to find a way to have MVX call this 
     ((BaseViewModel)ViewModel).EndDeferringPropertyChangedEvents(); 

그러나 기술적 인 측면에서 볼 때이 Deferring 코드가 필요한 이유를 더 자세히 검토하고 이해하는 것이 도움이 될 수 있다고 생각합니다. 기본적인 스레딩 문제가 무엇인지 살펴보십시오.

bindings.Apply(); 모든 현재 바운드 속성 값이 ViewViewModel에서 전송해야합니다 라인 중 현재 ::

  1. 에서 저를 당혹 게하는 요인이 될 것입니다 - 그래서에서 EndDeferringPropertyChangedEvents();를 호출은 다음 줄은 (이론적으로) 다른 값을 거의 얻지 않아야합니다.

  2. 또한 기본 MvvmCross RaisePropertyChanged 메서드는 UI 스레드로 알림을 변경했습니다. ViewDidLoad도 UI 스레드에서 호출되므로 ViewDidLoad 중에 백그라운드 스레드에서 수행 한 RaisePropertyChanged 호출은 모두 ViewDidLoad이 완료되고 UI 스레드가 사용 가능해질 때까지 자동으로 지연됩니다.

     // check for subscription before potentially causing a cross-threaded call 
         if (PropertyChanged == null) 
          return; 
    

    (https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNotifyPropertyChanged.cs#L76에서)

  3. : System의 - 스레딩이 자동 RaisePropertyChanged 연기를 통해 방법을 찾을 수있는 곳 MvxNotifyPropertyChanged 코드를 보면

  4. , 유일한 잠재적 인 차이가 나는이 최적화 검사에 볼 수 있습니다

  5. ViewModel Init 방법도 인 경우 Task 관리이므로이 async 코드는 UI 스레드를 사용해야합니다. 이 비동기 작업의 "콜백"도 UI 스레드로 마샬링되어야합니다 (따라서 ViewDidLoad 자체에서는 실행해서는 안 됨).

내가 말했듯이, 이러한 요인들은 나를 당황스럽게 만들고있다 - 나는 명확한 대답/설명이 없다 - 미안하다! 하지만 예제 문제를보고 일반적인 수준에서 문제를 해결하는 데 도움을주고 싶습니다.

+0

귀하의 의견은 문제가 Google 코드의 일부로 인해 발생했음을 의심스럽게합니다. 조금만 더 살펴 보겠습니다. 바인딩 프로세스에 대한 설명 주셔서 감사합니다 – geoffreys

+0

행운을 빕니다. 나는 이것이 일반적인 문제가 될 수 있다는 생각에 여전히 열려 있습니다. 멀티 스레딩은 로직에서 갭을 찾는 방법을 가지고 있습니다. – Stuart

+0

나는 정확한 원인을 찾아 낼 수 없었고, 20 건의 사형마다 하나씩, 그리고 오직 한 화면에서만 말하고있다. 이제 해결 방법을 사용하고 나중에 원인을 찾으려고합니다. – geoffreys

관련 문제