1
0
Эх сурвалжийг харах

Add IActivityApplicationLifetime for android (#18893)

* add lifetime with view factory on android

* rename android lifetime interface

* add warning when using ISingleViewApplicationLifetime for android, set current main activity reference on OnResume

* fix nit
Emmanuel Hansen 3 сар өмнө
parent
commit
56d94d64b9

+ 8 - 0
samples/ControlCatalog/App.xaml.cs

@@ -44,6 +44,10 @@ namespace ControlCatalog
             {
                 desktopLifetime.MainWindow = new MainWindow { DataContext = new MainWindowViewModel() };
             }
+            else if(ApplicationLifetime is IActivityApplicationLifetime singleViewFactoryApplicationLifetime)
+            {
+                singleViewFactoryApplicationLifetime.MainViewFactory = () => new MainView { DataContext = new MainWindowViewModel() };
+            }
             else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
             {
                 singleViewLifetime.MainView = new MainView { DataContext = new MainWindowViewModel() };
@@ -97,6 +101,10 @@ namespace ControlCatalog
                     newWindow.Show();
                     oldWindow?.Close();
                 }
+                else if (app.ApplicationLifetime is IActivityApplicationLifetime singleViewFactoryApplicationLifetime)
+                {
+                    singleViewFactoryApplicationLifetime.MainViewFactory = () => new MainView { DataContext = new MainWindowViewModel() };
+                }
                 else if (app.ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
                 {
                     singleViewLifetime.MainView = new MainView();

+ 4 - 0
samples/SafeAreaDemo/App.xaml.cs

@@ -19,6 +19,10 @@ namespace SafeAreaDemo
             {
                 desktop.MainWindow = new MainWindow();
             }
+            else if (ApplicationLifetime is IActivityApplicationLifetime singleViewFactoryApplicationLifetime)
+            {
+                singleViewFactoryApplicationLifetime.MainViewFactory = () => new MainView();
+            }
             else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewPlatform)
             {
                 singleViewPlatform.MainView = new MainView();

+ 4 - 0
samples/SingleProjectSandbox/App.axaml.cs

@@ -21,6 +21,10 @@ public class App : Application
         {
             desktopLifetime.MainWindow = new MainWindow();
         }
+        else if (ApplicationLifetime is IActivityApplicationLifetime singleViewFactoryApplicationLifetime)
+        {
+            singleViewFactoryApplicationLifetime.MainViewFactory = () => new MainView();
+        }
         else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
         {
             singleViewLifetime.MainView = new MainView();

+ 28 - 0
src/Android/Avalonia.Android/ApplicationLifetime.cs

@@ -0,0 +1,28 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Logging;
+
+namespace Avalonia.Android;
+
+internal class ApplicationLifetime : IActivityApplicationLifetime, ISingleViewApplicationLifetime
+{
+    private Control? _mainView;
+
+    public Func<Control>? MainViewFactory { get; set; }
+
+    public Control? MainView
+    {
+        get => _mainView; set
+        {
+            _mainView = value;
+
+            Logger.TryGet(LogEventLevel.Warning, LogArea.AndroidPlatform)?.Log(this, "ISingleViewApplicationLifetime.MainView is not fully supported on Android." +
+                " Consider setting IActivityApplicationLifetime.MainViewFactory.");
+            if (_mainView != null)
+                MainViewFactory = () => _mainView;
+            else
+                MainViewFactory = null;
+        }
+    }
+}

+ 3 - 3
src/Android/Avalonia.Android/AvaloniaAndroidApplication.cs

@@ -9,13 +9,13 @@ namespace Avalonia.Android
 {
     internal interface IAndroidApplication
     {
-        SingleViewLifetime? Lifetime { get; set; }
+        ApplicationLifetime? Lifetime { get; set; }
     }
 
     public class AvaloniaAndroidApplication<TApp> : global::Android.App.Application, IAndroidApplication
         where TApp : Application, new()
     {
-        SingleViewLifetime? IAndroidApplication.Lifetime { get; set; }
+        ApplicationLifetime? IAndroidApplication.Lifetime { get; set; }
 
         protected AvaloniaAndroidApplication(nint javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
         {
@@ -32,7 +32,7 @@ namespace Avalonia.Android
             var builder = CreateAppBuilder();
             builder = CustomizeAppBuilder(builder);
 
-            var lifetime = new SingleViewLifetime();
+            var lifetime = new ApplicationLifetime();
 
             ((IAndroidApplication)this).Lifetime = lifetime;
 

+ 20 - 3
src/Android/Avalonia.Android/AvaloniaMainActivity.cs

@@ -12,14 +12,20 @@ public class AvaloniaMainActivity : AvaloniaActivity
     {
         if (Application is IAndroidApplication application && application.Lifetime is { } lifetime)
         {
-            initialContent ??= lifetime.MainView; 
+            initialContent ??= lifetime.MainViewFactory?.Invoke();
 
-            _view = new AvaloniaView(this) { Content = initialContent };
-            lifetime.Activity = this;
+            _view = new AvaloniaView(this);
+
+            Content = initialContent;
         }
 
         if (_view is null)
             throw new InvalidOperationException("Unknown error: AvaloniaView initialization has failed.");
+    }
+
+    protected override void OnResume()
+    {
+        base.OnResume();
 
         if (Avalonia.Application.Current?.TryGetFeature<IActivatableLifetime>()
             is AndroidActivatableLifetime activatableLifetime)
@@ -28,6 +34,17 @@ public class AvaloniaMainActivity : AvaloniaActivity
         }
     }
 
+    protected override void OnDestroy()
+    {
+        base.OnDestroy();
+
+        if (Avalonia.Application.Current?.TryGetFeature<IActivatableLifetime>()
+            is AndroidActivatableLifetime activatableLifetime && activatableLifetime.CurrentMainActivity == this)
+        {
+            activatableLifetime.CurrentMainActivity = null;
+        }
+    }
+
     protected virtual AppBuilder CreateAppBuilder() => AppBuilder.Configure<Application>().UseAndroid();
     protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder;
 }

+ 0 - 46
src/Android/Avalonia.Android/SingleViewLifetime.cs

@@ -1,46 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using Avalonia.Controls;
-using Avalonia.Controls.ApplicationLifetimes;
-
-namespace Avalonia.Android;
-
-internal class SingleViewLifetime : ISingleViewApplicationLifetime, ISingleTopLevelApplicationLifetime
-{
-    private Control? _mainView;
-    private AvaloniaMainActivity? _activity;
-        
-    /// <summary>
-    /// Since Main Activity can be swapped, we should adjust lifetime as well.
-    /// </summary>
-    public AvaloniaMainActivity Activity
-    {
-        [return: MaybeNull] get => _activity!;
-        internal set
-        {
-            if (_activity != null)
-            {
-                _activity.Content = null;
-            }
-            _activity = value;
-            _activity.Content = _mainView;
-        }
-    }
-
-    public Control? MainView
-    {
-        get => _mainView;
-        set
-        {
-            if (_mainView != value)
-            {
-                _mainView = value;
-                if (_activity != null)
-                {
-                    _activity.Content = _mainView;
-                }
-            }
-        }
-    }
-
-    public TopLevel? TopLevel => _activity?._view?.TopLevel;
-}

+ 11 - 0
src/Avalonia.Controls/ApplicationLifetimes/IActivityApplicationLifetime.cs

@@ -0,0 +1,11 @@
+using System;
+using Avalonia.Metadata;
+
+namespace Avalonia.Controls.ApplicationLifetimes
+{
+    [NotClientImplementable]
+    public interface IActivityApplicationLifetime : IApplicationLifetime
+    {
+        Func<Control>? MainViewFactory { get; set; }
+    }
+}