From 60e664ab26f12c619284cf002c37323470c17a30 Mon Sep 17 00:00:00 2001 From: leo Date: Sat, 2 Mar 2024 22:45:14 +0800 Subject: [PATCH] optimize<*>: use custom view locator instead of ContentControl.DataTemplates to avoid memory leak. --- src/ViewModels/Launcher.cs | 15 ++++++--------- src/ViewModels/LauncherPage.cs | 12 ++++++------ src/Views/Histories.axaml.cs | 6 ------ src/Views/Launcher.axaml | 4 ++-- src/Views/Launcher.axaml.cs | 28 ++++++++++++++++++++++++++++ src/Views/Repository.axaml | 20 +------------------- src/Views/Repository.axaml.cs | 34 ++++++++++++++++++++++++++++++++++ src/Views/StashesPage.axaml.cs | 7 ------- src/Views/WorkingCopy.axaml.cs | 13 ------------- 9 files changed, 77 insertions(+), 62 deletions(-) diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index bd5fed44..97877a6d 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -160,26 +160,23 @@ namespace SourceGit.ViewModels { } else { page = ActivePage; page.Node = node; - page.View = new Views.Repository() { DataContext = repo }; + page.Data = repo; } } else { page.Node = node; - page.View = new Views.Repository() { DataContext = repo }; + page.Data = repo; } ActivePage = page; } private void CloseRepositoryInTab(LauncherPage page) { - if (page.Node.IsRepository) { - var repo = Preference.FindRepository(page.Node.Id); - if (repo != null) { - Commands.AutoFetch.RemoveRepository(repo.FullPath); - repo.Close(); - } + if (page.Data is Repository repo) { + Commands.AutoFetch.RemoveRepository(repo.FullPath); + repo.Close(); } - page.View = null; + page.Data = null; } private LauncherPage _activePage = null; diff --git a/src/ViewModels/LauncherPage.cs b/src/ViewModels/LauncherPage.cs index c147c270..4be607f5 100644 --- a/src/ViewModels/LauncherPage.cs +++ b/src/ViewModels/LauncherPage.cs @@ -8,9 +8,9 @@ namespace SourceGit.ViewModels { set => SetProperty(ref _node, value); } - public object View { - get => _view; - set => SetProperty(ref _view, value); + public object Data { + get => _data; + set => SetProperty(ref _data, value); } public AvaloniaList Notifications { @@ -25,12 +25,12 @@ namespace SourceGit.ViewModels { Bookmark = 0, IsRepository = false, }; - _view = new Views.Welcome() { DataContext = new Welcome() }; + _data = new Welcome(); } public LauncherPage(RepositoryNode node, Repository repo) { _node = node; - _view = new Views.Repository() { DataContext = repo }; + _data = repo; } public override string GetId() { @@ -48,6 +48,6 @@ namespace SourceGit.ViewModels { } private RepositoryNode _node = null; - private object _view = null; + private object _data = null; } } diff --git a/src/Views/Histories.axaml.cs b/src/Views/Histories.axaml.cs index b05cee07..775f21e1 100644 --- a/src/Views/Histories.axaml.cs +++ b/src/Views/Histories.axaml.cs @@ -1,7 +1,6 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; -using Avalonia.Interactivity; using Avalonia.Media; using Avalonia.VisualTree; using System; @@ -208,11 +207,6 @@ namespace SourceGit.Views { InitializeComponent(); } - protected override void OnUnloaded(RoutedEventArgs e) { - base.OnUnloaded(e); - GC.Collect(); - } - private void OnCommitDataGridLayoutUpdated(object sender, EventArgs e) { commitGraph.InvalidateVisual(); } diff --git a/src/Views/Launcher.axaml b/src/Views/Launcher.axaml index c98ad8fb..066ee207 100644 --- a/src/Views/Launcher.axaml +++ b/src/Views/Launcher.axaml @@ -223,8 +223,8 @@ - - + + diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index 4ba8fe43..c77e051a 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -23,6 +23,34 @@ namespace SourceGit.Views { } } + public class LauncherBody : Border { + public static readonly StyledProperty DataProperty = + AvaloniaProperty.Register(nameof(Data), false); + + public object Data { + get => GetValue(DataProperty); + set => SetValue(DataProperty, value); + } + + protected override Type StyleKeyOverride => typeof(Border); + + static LauncherBody() { + DataProperty.Changed.AddClassHandler((body, ev) => { + var data = body.Data; + + if (data == null) { + body.Child = null; + } else if (data is ViewModels.Welcome) { + body.Child = new Welcome { DataContext = data }; + } else if (data is ViewModels.Repository) { + body.Child = new Repository { DataContext = data }; + } else { + body.Child = null; + } + }); + } + } + public partial class Launcher : Window, Models.INotificationReceiver { public Launcher() { DataContext = new ViewModels.Launcher(); diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index fc581b54..18fcaa69 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -447,25 +447,7 @@