2013-07-25 26 views
5

Tôi cần có khả năng chặn khung và thực hiện quá trình khởi tạo lại khi ViewModel đang được tải lại từ bộ nhớ cache. Vì ViewModel không được tạo lại, tôi không thể sử dụng phương thức Init(), MvxViewModel.InitFromBundle, cũng như MvxViewModel.ReloadFromBundle.MvvmCross ViewModel caching và tái khởi tạo

Tôi đang cố gắng gỡ lỗi một tình huống trong đó nhấp vào nút quay lại khôi phục Chế độ xem có trạng thái không nhất quán. Một số loại MvxViewModel.OnReloading() sẽ giúp ích.

Có cách nào để thực hiện việc này trong v3 không?

EDIT:

Giả sử tôi có FirstPageViewModel đó cho thấy một lệnh để điều hướng đến SecondPageViewModel. Dựa trên những gì tôi đang quan sát, nếu bạn nhấp vào nút quay lại của trình mô phỏng trong khi trên SecondPageView, FirstPageViewModel không được xây dựng. Thay vào đó, nó được lấy ra, tôi tin rằng, từ một số bộ nhớ cache, sau đó bị ràng buộc để xem. Bộ nhớ cache này có thể là cài đặt bộ nhớ cache IMvxSingleViewModel.

Do đó, luồng thông thường sau khi xây dựng ViewModel, nơi bạn gọi Init(), InitFromBundle() và ReloadFromBundle() không áp dụng trong trường hợp này. Nói cách khác, tôi cần một cách để khởi tạo lại một ViewModel bất kể nó chỉ mới được xây dựng hay nó được hồi sinh từ bộ nhớ cache. Nếu trước đây, tôi có thể sử dụng phương thức Init(). Nếu sau này là đúng, không có cách nào để làm điều này trong chính ViewModel.

Đây là vấn đề:

Tôi có một thể hiện của ICollectionService được truyền từ FirstViewModel để SecondViewModel. FirstView cũng chứa một ListView được liên kết với CollectionService này. Vì CollectionService không được gõ mạnh nên tôi có thể truyền nó xung quanh và sử dụng mẫu mục thích hợp để hiển thị các mục của nó trong khung nhìn.

Trước khi hiển thị SecondViewModel, FirstViewModel truy xuất một số dữ liệu từ xa và điền vào CollectionService. Khi SecondViewModel được hiển thị, khung nhìn của nó hiển thị dữ liệu từ CollectionService bằng cách sử dụng một mẫu mục khác. Tuy nhiên, nếu tôi điều hướng trở lại, vì FirstViewModel vẫn đang tham chiếu đến CollectionService, FirstView sẽ hiển thị dữ liệu đã được SecondViewModel sử dụng trừ khi FirstViewModel có thể được khởi tạo lại, xóa Bộ sưu tập trong quá trình. Có lẽ cách tiếp cận là sai nhưng đây là điểm mấu chốt của vấn đề của tôi.

Tôi không biết liệu nền tảng có tạo sự khác biệt hay không, vì tôi mong đợi hành vi tương tự trên Windows Phone và iOS khi việc khởi tạo lại này sẽ xảy ra trong mô-đun chính. Tuy nhiên đây là những quan sát trên Android.

TIA.

+0

Nó không hoàn toàn rõ ràng với tôi những gì bạn đang hỏi, "bộ đệm" là gì, cái gì không nhất quán trong trạng thái của bạn, bạn đang làm gì hoặc bạn đang cố gắng làm gì. Một ví dụ về luồng người dùng và/hoặc một số mã ví dụ về vấn đề có thể hữu ích. – Stuart

+0

Stuart, cảm ơn phản hồi. Tôi vừa chỉnh sửa câu hỏi của mình với thông tin bổ sung. –

Trả lời

5

Cảm ơn bạn đã cập nhật câu hỏi của mình để cung cấp nhiều thông tin hơn.

Sử dụng phương pháp tiếp cận MvvmCross cho phát triển đa nền tảng cho phép bạn tận dụng nền tảng UI gốc. Điều này có nghĩa là bạn - nhà phát triển - không cần phải tìm hiểu một chút về những nền tảng này - và một trong những điều quan trọng cần hiểu là vòng đời "xem", kể cả khi được sử dụng trong ngăn xếp điều hướng.

Theo mặc định, MvvmCross không lưu bộ nhớ cache các mô hình xem cho bất kỳ khoảng thời gian đáng kể nào. Đôi khi có các bộ đệm ngắn ngủi xảy ra trong quá trình chuyển đổi màn hình (ví dụ xoay) nhưng không có bộ nhớ cache dài hạn. Thay vào đó, khi một chế độ xem mới được tạo thì mvx theo mặc định sẽ tạo một mô hình chế độ xem mới để đi cùng với nó - và cặp đó ở lại với nhau "cho cuộc sống" - với phần cuối của cuộc sống được xác định bởi chế độ xem.

Tôi khuyến khích bạn dành chút thời gian để đọc về các mô hình vòng đời cơ bản và điều hướng trên mỗi nền tảng.

  • trên iOS điều này có nghĩa đặc biệt là tìm hiểu về UINavigationController mà duy trì một chồng UIViewControllers trong bộ nhớ (mỗi trong số đó sẽ ở mvx được kết hôn với một viewmodel cá nhân)

  • tình hình cũng tương tự như trong WindowsPhone với RootFrame duy trì trong RAM một chồng các trang. Có một biến chứng ở đây - kinh ngạc - nhưng quên đi điều đó cho đến sau khi bạn nhận được vòng đời cơ bản đóng đinh.

  • trên Android, tình hình tương tự, nhưng hơi khác. Đối với các ứng dụng cơ bản, bạn có thể giả định rằng Android sẽ duy trì một chồng các trang Hoạt động trong RAM trong suốt thời gian sử dụng ứng dụng của bạn. Tuy nhiên, Android thực sự phức tạp hơn nhiều so với điều đó - hệ điều hành có thể loại bỏ các mục backstack khỏi RAM khi nó quyết định đòi lại bộ nhớ. Trong những trường hợp này, có một số 'kinh ngạc' và mất nước đôi khi lo lắng - nhưng, một lần nữa tôi khuyên bạn nên bỏ qua điều đó cho đến sau khi bạn có những điều cơ bản dưới đai.

  • trên winrt, theo mặc định tình hình thực sự là những gì bạn hiểu trong mô tả của mình - backstack chỉ chứa thông tin trạng thái - bản thân chế độ xem không được lưu trong bộ nhớ RAM.

Những câu chuyện trên hy vọng sẽ mang đến cho bạn một số ý tưởng về vòng đời điều hướng trên mỗi nền tảng - và do đó cũng mang lại cho bạn vòng đời viewmodel.


Bây giờ, nếu bạn đang ở trong tình huống mà bạn muốn viewmodels của bạn (hoặc một số đối tượng mức độ ứng dụng khác) để biết về tình trạng xem tầm nhìn, sau đó bạn sẽ cần phải chặn một số sự kiện quan điểm trên mỗi nền tảng và chuyển các sự kiện này qua các mô hình xem.

Ví dụ: FirstViewModel của bạn có thể hiển thị OnMadeVisible() làm Api tùy chỉnh. Trong trường hợp đó, bạn có thể đảm bảo điều này được gọi là từ OnNavigatedTo trên Windows, OnResume trên Android và viewDidAppear trên iOS


Hoặc nếu bạn đang xem xét cơ chế chung để giao tiếp ViewModel-ViewModel sau đó tôi sẽ khuyên bạn nhìn vào một cái gì đó như


Lưu ý:

Rõ ràng, chuyển hướng ngăn xếp không phải là chuyển hướng chỉ mô - nếu ứng dụng của bạn cũng sử dụng flyouts, tab, splitviews, hamburger, vv sau đó bạn sẽ cần phải hiểu những vòng đời xem quá.

Nếu bao giờ bạn có nghi ngờ về Chế độ xem vòng đời, sau đó thêm dấu vết để nhà thầu của họ và các sự kiện vòng đời chính là một bước đầu tiên tốt,


Là một lưu ý cuối cùng, nếu bạn quyết định vị trí viewmodel mặc định và vòng đời viewmodel không phải là những gì ứng dụng của bạn cần - ví dụ nếu bạn muốn sử dụng các dạng xem đơn lẻ, thì điều này có thể dễ dàng đạt được - xem xét ghi đè định vị mô hình xem trong lớp App.cs của bạn.

+0

Stuart, cảm ơn phản hồi chi tiết. Tôi đang cố gắng học như tôi đi cùng vì vậy đây là những thứ rất hữu ích. Tôi đã đọc vòng đời hoạt động của Andriod đã cung cấp cho Xamarin của tôi để đạt được một sự hiểu biết cơ bản nhưng tôi đoán có nhiều câu chuyện hơn. Andriod dường như tái tạo các hoạt động đã được điều hướng khỏi khi phương thức OnCreate được gọi mỗi lần, mặc dù ViewModel tương ứng không được tạo lại. Sẽ tiếp tục đọc .... cảm ơn. –

+0

"phương pháp OnCreate được gọi mỗi lần, mặc dù ViewModel tương ứng không được tái tạo" - không phải là điều nên xảy ra. Không có tranh luận về nó. Nếu bạn nghĩ rằng có một lỗi, xin vui lòng gửi một trường hợp tái sản xuất một nơi nào đó và đưa ra một vấn đề. – Stuart

+0

Ok, sẽ xem xét cảm ơn này. Một câu hỏi liên quan. Mô hình được đề nghị để làm sạch khi ViewModel đang được xử lý là gì? Tôi có nên ghi đè SaveStateToBundle hoặc triển khai IDisposable không? Nếu không, nó sẽ là một ý tưởng tốt cho MvxViewModel cung cấp một phương pháp ảo như OnTerminating hoặc một cái gì đó? –

0

Ngay cả khi biết rằng câu hỏi này là 3 tuổi, tôi không chắc chắn nếu có một cách để làm điều đó trong phiên bản hiện tại, nhưng tôi đã làm điều đó một mình. Trong ví dụ này, tôi sẽ tạo một lớp tĩnh chứa tất cả các cá thể của các ViewModels trong ứng dụng. Nó bắt đầu với các biến tĩnh null và nhận được mỗi giá trị khi mỗi ViewModel được khởi tạo (trên phương thức khởi tạo).

public static class ViewStackService 
{ 
    //Stack 
    private static exmp1ViewModel exmp1 = null; 
    private static exmp2ViewModel exmp2 = null; 
    private static exmp3ViewModel exmp3 = null; 

    public static void addStackLevel(exmp1ViewModel _parent) 
    { 
     exmp1 = _parent; 
    } 

    public static void addStackLevel(exmp2ViewModel _parent) 
    { 
     exmp2 = _parent; 
    } 

    public static void addStackLevel(exmp3ViewModel _parent) 
    { 
     exmp3 = _parent; 
    } 


    public static async void burnAll() 
    { 

     if (exmp3 != null) 
     { 
      exmp3.DoBackCommand(); 
      await Task.Delay(250); 
      exmp3 = null; 
     } 
     if (exmp2 != null) 
     { 
      //the OnResume method can be implemented here 
      exmp2.DoBackCommand(); 
      await Task.Delay(250); 
      exmp2 = null; 
     } 
     if (exmp1 != null) 
     { 
      //the OnResume method can be implemented here 
      exmp1.DoBackCommand(); 
      await Task.Delay(250); 
      exmp1 = null; 
     } 
    } 
} 

Những ViewModels sử dụng như các biến nhận các trường hợp khi một constructor của mỗi ViewModel được đưa ra:

public class exmp1ViewModel 
    : MvxViewModel 
{ 
    public exmp3ViewModel(){ 
     ViewStackService.addStackLevel (this); 
    } 
} 

Phương pháp burnAll() sẽ đóng cửa tất cả các ViewModels khi gọi. Đó là vấn đề bởi vì khi tôi đặt thời gian mà chuỗi sẽ chờ theo cách thủ công, nó có thể có lỗi trong một số thiết bị khác nhau, làm giảm hiệu suất của nó. Nhưng khi sử dụng lớp đó, bạn có thể thực hiện một số thứ khác, như kiểm tra xem ViewModel đã được khởi tạo trước đó để khởi tạo một lớp mới hay sử dụng lớp để thực hiện phương thức OnResume được gọi khi ViewModel được hiển thị lại. Chỉ cần nhớ rằng một thể hiện chỉ có thể được sử dụng khi nó không bị tạm dừng, tức là bạn chỉ có thể gọi các phương thức của một ViewModel khi nó đang được ứng dụng sử dụng.

Các vấn đề liên quan