Każda technologia ma swoje zalety i wady. Prism także nie jest pozbawiony wad. Jedną z bardziej widocznych wad jest wycieka pamięci podczas stosowania podregionów. Memory leak, czyli sytuacja w której obiekt jest przechowywany w pamięci, ale nie można się do niego odwołać jest z pewnością jedną z największych bolączek programistycznych. W tym poście postaram się wyjaśnić gdzie znajduje się owy wyciek oraz na podstawie wpisu na blogu Damian Schenkelman-a pokaże w jaki sposób można ominąć ten problem.
Cały problem można znaleźć oficjalnie opisany pod tym
adresem.
Podany jest tam także przykład aplikacji, w którym widać efekt działania memory leak-a. Mamy następującą aplikację:
Całość jest zrozumiała i prosta. Po kliknięciu na przycisk Remove MainView from MainRegion oczekujemy, że główny widok wraz z jego pod widokami zostanie usunięty. Drugi przycisk Check RegionManager regions count, sprawdza ile jest aktualnie zarejestrowanych widoków.
Zobaczmy co się stanie w momencie kiedy najpierw usuniemy widoki a następnie wyświetlimy ilość zarejestrowanych widoków:
Jak widać zarejestrowanych widoków jest 3. Powinien być jeden. Pozostałe dwa widoki to TopRightView oraz BottomRightView. Nie zostały usunięte automatycznie.
Rozwiązaniem jest dosyć proste. W momencie zmiany w RegionManager należy przejść po wszystkich widokach regionu i usunąć je.
Realizuje je następująca klasa:
Code:
public class ClearChildViewsRegionBehavior : RegionBehavior
{
public const string BehaviorKey = "ClearChildViews";
protected override void OnAttach()
{
Region.PropertyChanged += RegionPropertyChanged;
}
void RegionPropertyChanged(object sender, System.ComponentModelPropertyChangedEventArgs e)
{
if (e.PropertyName != "RegionManager") return;
if (Region.RegionManager != null) return;
foreach (var dependencyObject in Region.Views.OfType<DependencyObject>())
{
dependencyObject.ClearValue(RegionManager.RegionManagerProperty);
}
}
}
Następnie zostaje jeszcze podpięcie klasy w Bootstrapperze:
Code:
protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
var regionBehaviorTypesDictionary = base.ConfigureDefaultRegionBehaviors();
regionBehaviorTypesDictionary.AddIfMissing
(ClearChildViewsRegionBehavior.BehaviorKey, typeof(ClearChildViewsRegionBehavior));
return regionBehaviorTypesDictionary;
}
Teraz po wykonaniu wcześniej opisanego usunięcia i zliczeniu ilości widoków w regionie powinniśmy uzyskać następujący wynik:
Brak komentarzy:
Prześlij komentarz