Browse Source

Seperate Avalonia lifecycle from android activity

Emmanuel Hansen 3 years ago
parent
commit
ebdb4e1974

+ 2 - 10
samples/ControlCatalog.Android/MainActivity.cs

@@ -5,16 +5,8 @@ using Avalonia.Android;
 
 namespace ControlCatalog.Android
 {
-    [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
-    public class MainActivity : AvaloniaActivity<App>
+    [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
+    public class MainActivity : AvaloniaActivity
     {
-        protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
-        {
-            return base.CustomizeAppBuilder(builder)
-                .AfterSetup(_ =>
-                {
-                    Pages.EmbedSample.Implementation = new EmbedSampleAndroid();
-                });
-        }
     }
 }

+ 12 - 1
samples/ControlCatalog.Android/SplashActivity.cs

@@ -1,12 +1,23 @@
 using Android.App;
 using Android.Content;
+using Android.Content.PM;
 using Android.OS;
+using Avalonia.Android;
 
 namespace ControlCatalog.Android
 {
     [Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
-    public class SplashActivity : Activity
+    public class SplashActivity : AvaloniaSplashActivity<App>
     {
+        protected override Avalonia.AppBuilder CustomizeAppBuilder(Avalonia.AppBuilder builder)
+        {
+            return base.CustomizeAppBuilder(builder)
+                 .AfterSetup(_ =>
+                 {
+                     Pages.EmbedSample.Implementation = new EmbedSampleAndroid();
+                 });
+        }
+
         protected override void OnCreate(Bundle? savedInstanceState)
         {
             base.OnCreate(savedInstanceState);

+ 17 - 49
src/Android/Avalonia.Android/AvaloniaActivity.cs

@@ -1,62 +1,42 @@
+using System;
+using Android.App;
+using Android.Content;
+using Android.Content.Res;
 using Android.OS;
+using Android.Runtime;
 using AndroidX.AppCompat.App;
-using Android.Content.Res;
 using AndroidX.Lifecycle;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Controls;
-using Android.Runtime;
-using Android.App;
-using Android.Content;
-using System;
 
 namespace Avalonia.Android
 {
     public abstract class AvaloniaActivity : AppCompatActivity
     {
-        internal class SingleViewLifetime : ISingleViewApplicationLifetime
-        {
-            public AvaloniaView View { get; internal set; }
-
-            public Control MainView
-            {
-                get => (Control)View.Content;
-                set => View.Content = value;
-            }
-        }
-
         internal Action<int, Result, Intent> ActivityResult;
         internal AvaloniaView View;
         internal AvaloniaViewModel _viewModel;
 
-        protected abstract AppBuilder CreateAppBuilder();
-
         protected override void OnCreate(Bundle savedInstanceState)
         {
-            var builder = CreateAppBuilder();
+            _viewModel = new ViewModelProvider(this).Get(Java.Lang.Class.FromType(typeof(AvaloniaViewModel))) as AvaloniaViewModel;
 
-
-            var lifetime = new SingleViewLifetime();
-
-            builder.AfterSetup(x =>
+            View = new AvaloniaView(this);
+            if (_viewModel.Content != null)
             {
-                _viewModel = new ViewModelProvider(this).Get(Java.Lang.Class.FromType(typeof(AvaloniaViewModel))) as AvaloniaViewModel;
+                View.Content = _viewModel.Content;
+            }
 
-                View = new AvaloniaView(this);
-                if (_viewModel.Content != null)
-                {
-                    View.Content = _viewModel.Content;
-                }
+            View.Prepare();
 
-                SetContentView(View);
+            if (Avalonia.Application.Current.ApplicationLifetime is SingleViewLifetime lifetime)
+            {
                 lifetime.View = View;
-
-                View.Prepare();
-            });
-
-            builder.SetupWithLifetime(lifetime);
+            }
 
             base.OnCreate(savedInstanceState);
+
+            SetContentView(View);
         }
+
         public object Content
         {
             get
@@ -90,16 +70,4 @@ namespace Avalonia.Android
             ActivityResult?.Invoke(requestCode, resultCode, data);
         }
     }
-
-    public abstract class AvaloniaActivity<TApp> : AvaloniaActivity where TApp : Application, new()
-    {
-        protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
-
-        protected override AppBuilder CreateAppBuilder()
-        {
-            var builder = AppBuilder.Configure<TApp>();
-
-            return CustomizeAppBuilder(builder);
-        }
-    }
 }

+ 34 - 0
src/Android/Avalonia.Android/AvaloniaSplashActivity.cs

@@ -0,0 +1,34 @@
+using Android.OS;
+using AndroidX.AppCompat.App;
+using AndroidX.Lifecycle;
+
+namespace Avalonia.Android
+{
+    public abstract class AvaloniaSplashActivity : AppCompatActivity
+    {
+        protected abstract AppBuilder CreateAppBuilder();
+
+        protected override void OnCreate(Bundle? savedInstanceState)
+        {
+            base.OnCreate(savedInstanceState);
+
+            var builder = CreateAppBuilder();
+
+            var lifetime = new SingleViewLifetime();
+
+            builder.SetupWithLifetime(lifetime);
+        }
+    }
+
+    public abstract class AvaloniaSplashActivity<TApp> : AvaloniaSplashActivity where TApp : Application, new()
+    {
+        protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
+
+        protected override AppBuilder CreateAppBuilder()
+        {
+            var builder = AppBuilder.Configure<TApp>();
+
+            return CustomizeAppBuilder(builder);
+        }
+    }
+}

+ 1 - 1
src/Android/Avalonia.Android/AvaloniaView.cs

@@ -74,7 +74,7 @@ namespace Avalonia.Android
 
         class ViewImpl : TopLevelImpl
         {
-            public ViewImpl(AvaloniaView avaloniaView) : base(avaloniaView)
+            public ViewImpl(AvaloniaView avaloniaView) : base(avaloniaView, true)
             {
                 View.Focusable = true;
                 View.FocusChange += ViewImpl_FocusChange;

+ 4 - 2
src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs

@@ -1,4 +1,5 @@
-using Avalonia.OpenGL.Egl;
+using Avalonia.OpenGL;
+using Avalonia.OpenGL.Egl;
 using Avalonia.OpenGL.Surfaces;
 
 namespace Avalonia.Android.OpenGL
@@ -19,7 +20,8 @@ namespace Avalonia.Android.OpenGL
 
         public static GlPlatformSurface TryCreate(IEglWindowGlPlatformSurfaceInfo info)
         {
-            if (EglPlatformOpenGlInterface.TryCreate() is EglPlatformOpenGlInterface egl)
+            var feature = AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>();
+            if (feature is EglPlatformOpenGlInterface egl)
             {
                 return new GlPlatformSurface(egl, info);
             }

+ 0 - 7
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@@ -3,20 +3,14 @@ using System.Collections.Generic;
 
 using Android.Content;
 using Android.Graphics;
-using Android.Media.TV;
-using Android.OS;
 using Android.Runtime;
-using Android.Text;
 using Android.Views;
 using Android.Views.InputMethods;
-using Android.Widget;
 using Avalonia.Android.OpenGL;
-using Avalonia.Android.Platform.Input;
 using Avalonia.Android.Platform.Specific;
 using Avalonia.Android.Platform.Specific.Helpers;
 using Avalonia.Android.Platform.Storage;
 using Avalonia.Controls;
-using Avalonia.Controls.Documents;
 using Avalonia.Controls.Platform;
 using Avalonia.Controls.Platform.Surfaces;
 using Avalonia.Input;
@@ -29,7 +23,6 @@ using Avalonia.Platform.Storage;
 using Avalonia.Rendering;
 using Avalonia.Rendering.Composition;
 using Java.Lang;
-using static System.Net.Mime.MediaTypeNames;
 
 namespace Avalonia.Android.Platform.SkiaPlatform
 {

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

@@ -0,0 +1,26 @@
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+
+namespace Avalonia.Android
+{
+    internal class SingleViewLifetime : ISingleViewApplicationLifetime
+    {
+        private AvaloniaView _view;
+
+        public AvaloniaView View
+        {
+            get => _view; internal set
+            {
+                if (_view != null)
+                {
+                    _view.Content = null;
+                    _view.Dispose();
+                }
+                _view = value;
+                _view.Content = MainView;
+            }
+        }
+
+        public Control MainView { get; set; }
+    }
+}