Kaynağa Gözat

Simplify UIViewControlHandle/AndroidViewControlHandle

Max Katz 3 yıl önce
ebeveyn
işleme
6260829702

+ 28 - 27
Avalonia.sln

@@ -219,11 +219,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.SourceGenerator",
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevAnalyzers", "src\tools\DevAnalyzers\DevAnalyzers.csproj", "{2B390431-288C-435C-BB6B-A374033BD8D1}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeEmbedSample.Android", "samples\interop\NativeEmbedSample.Android\NativeEmbedSample.Android.csproj", "{7D287579-7DB4-4415-A52A-46A5CD6FE30F}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeEmbedSample.Android", "samples\interop\NativeEmbedSample.Android\NativeEmbedSample.Android.csproj", "{7D287579-7DB4-4415-A52A-46A5CD6FE30F}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeEmbedSample.Desktop", "samples\interop\NativeEmbedSample.Desktop\NativeEmbedSample.Desktop.csproj", "{F2389463-DDB4-4317-B894-D4DF9FF6B763}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeEmbedSample.Desktop", "samples\interop\NativeEmbedSample.Desktop\NativeEmbedSample.Desktop.csproj", "{F2389463-DDB4-4317-B894-D4DF9FF6B763}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeEmbedSample.iOS", "samples\interop\NativeEmbedSample.iOS\NativeEmbedSample.iOS.csproj", "{28DB5AD1-656D-4619-BE0B-5B475E138DF8}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NativeEmbedSample.iOS", "samples\interop\NativeEmbedSample.iOS\NativeEmbedSample.iOS.csproj", "{28DB5AD1-656D-4619-BE0B-5B475E138DF8}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -1419,6 +1419,30 @@ Global
 		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhone.Build.0 = Release|Any CPU
 		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|Any CPU.Build.0 = Release|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|iPhone.Build.0 = Release|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 		{3278F3A9-9509-4A3F-A15B-BDC8B5BFF632}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
 		{3278F3A9-9509-4A3F-A15B-BDC8B5BFF632}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
 		{3278F3A9-9509-4A3F-A15B-BDC8B5BFF632}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
@@ -1971,30 +1995,6 @@ Global
 		{2B390431-288C-435C-BB6B-A374033BD8D1}.Release|iPhone.Build.0 = Release|Any CPU
 		{2B390431-288C-435C-BB6B-A374033BD8D1}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{2B390431-288C-435C-BB6B-A374033BD8D1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|Any CPU.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|iPhone.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|iPhone.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|iPhone.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|Any CPU.Build.0 = Release|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|iPhone.ActiveCfg = Release|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|iPhone.Build.0 = Release|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{1ECC012A-8837-4AE2-9BDA-3E2857898727}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
@@ -2009,6 +2009,7 @@ Global
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Debug|iPhone.Build.0 = Debug|Any CPU
 		{7D287579-7DB4-4415-A52A-46A5CD6FE30F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU

+ 9 - 33
samples/interop/NativeEmbedSample/Android/EmbedSample.Android.cs

@@ -1,10 +1,6 @@
 #if __ANDROID__ || ANDROID
-using System;
-using System.IO;
-using System.Diagnostics;
-using Android.Views;
-using Avalonia.Controls.Platform;
 using Avalonia.Platform;
+using Avalonia.Android;
 
 namespace NativeEmbedSample;
 
@@ -12,23 +8,27 @@ public partial class EmbedSample
 {
     private IPlatformHandle CreateAndroid(IPlatformHandle parent)
     {
+        var parentContext = (parent as AndroidViewControlHandle)?.View.Context
+            ?? Android.App.Application.Context;
+
         if (IsSecond)
         {
-            var webView = new Android.Webkit.WebView(Android.App.Application.Context);
+            var webView = new Android.Webkit.WebView(parentContext);
             webView.LoadUrl("https://www.android.com/");
 
-            return new AndroidViewHandle(webView);
+            return new AndroidViewControlHandle(webView);
         }
         else
         {
-            var button = new Android.Widget.Button(Android.App.Application.Context) { Text = "Hello world" };
+            var button = new Android.Widget.Button(parentContext) { Text = "Hello world" };
             var clickCount = 0;
             button.Click += (sender, args) =>
             {
                 clickCount++;
                 button.Text = $"Click count {clickCount}";
             };
-            return new AndroidViewHandle(button);   
+
+            return new AndroidViewControlHandle(button);
         }
     }
 
@@ -37,28 +37,4 @@ public partial class EmbedSample
         base.DestroyNativeControlCore(control);
     }
 }
-
-internal sealed class AndroidViewHandle : INativeControlHostDestroyableControlHandle
-{
-    private View _view;
-
-    public AndroidViewHandle(View view)
-    {
-        _view = view;
-    }
-
-    public IntPtr Handle => _view?.Handle ?? IntPtr.Zero;
-    public string HandleDescriptor => "JavaHandle";
-
-    public void Destroy()
-    {
-        _view?.Dispose();
-        _view = null;
-    }
-
-    ~AndroidViewHandle()
-    {
-        Destroy();
-    }
-}
 #endif

+ 6 - 0
samples/interop/NativeEmbedSample/NativeEmbedSample.csproj

@@ -27,6 +27,12 @@
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
   </ItemGroup>
+  <ItemGroup Condition="'$(TargetFramework)' == 'net6.0-android'">
+    <ProjectReference Include="..\..\..\src\Android\Avalonia.Android\Avalonia.Android.csproj" />
+  </ItemGroup>
+  <ItemGroup Condition="'$(TargetFramework)' == 'net6.0-ios'">
+    <ProjectReference Include="..\..\..\src\iOS\Avalonia.iOS\Avalonia.iOS.csproj" />
+  </ItemGroup>
 
   <Import Project="..\..\..\build\BuildTargets.targets" />
 </Project>

+ 3 - 25
samples/interop/NativeEmbedSample/iOS/EmbedSample.iOS.cs

@@ -1,13 +1,10 @@
 #if IOS
-using System;
-using System.IO;
-using System.Diagnostics;
-using Avalonia.Controls.Platform;
 using Avalonia.Platform;
 using CoreGraphics;
 using Foundation;
 using UIKit;
 using WebKit;
+using Avalonia.iOS;
 
 namespace NativeEmbedSample;
 
@@ -20,7 +17,7 @@ public partial class EmbedSample
             var webView = new WKWebView(CGRect.Empty, new WKWebViewConfiguration());
             webView.LoadRequest(new NSUrlRequest(new NSUrl("https://www.apple.com/")));
 
-            return new UIViewHandle(webView);
+            return new UIViewControlHandle(webView);
         }
         else
         {
@@ -34,7 +31,7 @@ public partial class EmbedSample
                 button.SetTitle($"Click count {clickCount}", UIControlState.Normal);
             }, UIControlEvent.TouchDown);
 
-            return new UIViewHandle(button);   
+            return new UIViewControlHandle(button);
         }
     }
 
@@ -43,23 +40,4 @@ public partial class EmbedSample
         base.DestroyNativeControlCore(control);
     }
 }
-
-internal class UIViewHandle : INativeControlHostDestroyableControlHandle
-{
-    private UIView _view;
-
-    public UIViewHandle(UIView view)
-    {
-        _view = view;
-    }
-
-    public IntPtr Handle => _view?.Handle ?? IntPtr.Zero;
-    public string HandleDescriptor => "UIView";
-
-    public void Destroy()
-    {
-        _view?.Dispose();
-        _view = null;
-    }
-}
 #endif

+ 32 - 0
src/Android/Avalonia.Android/AndroidViewControlHandle.cs

@@ -0,0 +1,32 @@
+#nullable enable
+
+using System;
+
+using Android.Views;
+
+using Avalonia.Controls.Platform;
+using Avalonia.Platform;
+
+namespace Avalonia.Android
+{
+    public class AndroidViewControlHandle : INativeControlHostDestroyableControlHandle
+    {
+        internal const string AndroidDescriptor = "JavaObjectHandle";
+
+        public AndroidViewControlHandle(View view)
+        {
+            View = view;
+        }
+
+        public View View { get; }
+
+        public string HandleDescriptor => AndroidDescriptor;
+
+        IntPtr IPlatformHandle.Handle => View.Handle;
+
+        public void Destroy()
+        {
+            View?.Dispose();
+        }
+    }
+}

+ 5 - 59
src/Android/Avalonia.Android/Platform/AndroidNativeControlHostImpl.cs

@@ -2,6 +2,7 @@
 
 using System;
 using System.Diagnostics.CodeAnalysis;
+
 using Android.Views;
 using Android.Widget;
 
@@ -21,16 +22,16 @@ namespace Avalonia.Android.Platform
 
         public INativeControlHostDestroyableControlHandle CreateDefaultChild(IPlatformHandle parent)
         {
-            return new AndroidViewControlHandle(new FrameLayout(_avaloniaView.Context!), false);
+            return new AndroidViewControlHandle(new FrameLayout(_avaloniaView.Context!));
         }
 
         public INativeControlHostControlTopLevelAttachment CreateNewAttachment(Func<IPlatformHandle, IPlatformHandle> create)
         {
-            var holder = new AndroidViewControlHandle(_avaloniaView, false);
+            var parent = new AndroidViewControlHandle(_avaloniaView);
             AndroidNativeControlAttachment? attachment = null;
             try
             {
-                var child = create(holder);
+                var child = create(parent);
                 // It has to be assigned to the variable before property setter is called so we dispose it on exception
 #pragma warning disable IDE0017 // Simplify object initialization
                 attachment = new AndroidNativeControlAttachment(child);
@@ -41,7 +42,6 @@ namespace Avalonia.Android.Platform
             catch
             {
                 attachment?.Dispose();
-                holder?.Destroy();
                 throw;
             }
         }
@@ -56,17 +56,13 @@ namespace Avalonia.Android.Platform
 
         public bool IsCompatibleWith(IPlatformHandle handle) => handle.HandleDescriptor == AndroidViewControlHandle.AndroidDescriptor;
 
-        class AndroidNativeControlAttachment : INativeControlHostControlTopLevelAttachment
+        private class AndroidNativeControlAttachment : INativeControlHostControlTopLevelAttachment
         {
-            // ReSharper disable once NotAccessedField.Local (keep GC reference)
-            private IPlatformHandle? _child;
             private View? _view;
             private AndroidNativeControlHostImpl? _attachedTo;
 
             public AndroidNativeControlAttachment(IPlatformHandle child)
             {
-                _child = child;
-
                 _view = (child as AndroidViewControlHandle)?.View
                     ?? Java.Lang.Object.GetObject<View>(child.Handle, global::Android.Runtime.JniHandleOwnership.DoNotTransfer);
             }
@@ -84,7 +80,6 @@ namespace Avalonia.Android.Platform
                 {
                     parent.RemoveView(_view);
                 }
-                _child = null;
                 _attachedTo = null;
                 _view?.Dispose();
                 _view = null;
@@ -137,53 +132,4 @@ namespace Avalonia.Android.Platform
             }
         }
     }
-
-    public class AndroidViewControlHandle : INativeControlHostDestroyableControlHandle, IDisposable
-    {
-        internal const string AndroidDescriptor = "JavaHandle";
-        
-        private View? _view;
-        private bool _disposeView;
-        
-        public AndroidViewControlHandle(View view, bool disposeView)
-        {
-            _view = view;
-            _disposeView = disposeView;
-        }
-        
-        public View View => _view ?? throw new ObjectDisposedException(nameof(AndroidViewControlHandle));
-        
-        public string HandleDescriptor => AndroidDescriptor;
-
-        IntPtr IPlatformHandle.Handle => _view?.Handle ?? default;
-
-        public void Destroy()
-        {
-            Dispose(true);
-        }
-        
-        void IDisposable.Dispose()
-        {
-            Dispose(true);
-        }
-        
-        ~AndroidViewControlHandle()
-        {
-            Dispose(false);
-        }
-        
-        private void Dispose(bool disposing)
-        {
-            if (_disposeView)
-            {
-                _view?.Dispose();
-            }
-
-            _view = null;
-            if (disposing)
-            {
-                GC.SuppressFinalize(this);
-            }
-        }
-    }
 }

+ 11 - 39
src/iOS/Avalonia.iOS/NativeControlHostImpl.cs

@@ -21,16 +21,16 @@ namespace Avalonia.iOS
 
         public INativeControlHostDestroyableControlHandle CreateDefaultChild(IPlatformHandle parent)
         {
-            return new UIViewControlHandle(new UIView(), true);
+            return new UIViewControlHandle(new UIView());
         }
 
         public INativeControlHostControlTopLevelAttachment CreateNewAttachment(Func<IPlatformHandle, IPlatformHandle> create)
         {
-            var holder = new UIViewControlHandle(_avaloniaView, false);
+            var parent = new UIViewControlHandle(_avaloniaView);
             NativeControlAttachment? attachment = null;
             try
             {
-                var child = create(holder);
+                var child = create(parent);
                 // It has to be assigned to the variable before property setter is called so we dispose it on exception
 #pragma warning disable IDE0017 // Simplify object initialization
                 attachment = new NativeControlAttachment(child);
@@ -41,7 +41,6 @@ namespace Avalonia.iOS
             catch
             {
                 attachment?.Dispose();
-                holder?.Destroy();
                 throw;
             }
         }
@@ -134,53 +133,26 @@ namespace Avalonia.iOS
             }
         }
     }
-    
-    public class UIViewControlHandle : INativeControlHostDestroyableControlHandle, IDisposable
+
+    public class UIViewControlHandle : INativeControlHostDestroyableControlHandle
     {
         internal const string UIViewDescriptor = "UIView";
+
         
-        private UIView? _view;
-        private bool _disposeView;
-        
-        public UIViewControlHandle(UIView view, bool disposeView)
+        public UIViewControlHandle(UIView view)
         {
-            _view = view;
-            _disposeView = disposeView;
+            View = view;
         }
         
-        public UIView View => _view ?? throw new ObjectDisposedException(nameof(UIViewControlHandle));
+        public UIView View { get; }
         
         public string HandleDescriptor => UIViewDescriptor;
 
-        IntPtr IPlatformHandle.Handle => _view?.Handle.Handle ?? default;
+        IntPtr IPlatformHandle.Handle => View.Handle.Handle;
 
         public void Destroy()
         {
-            Dispose(true);
-        }
-        
-        void IDisposable.Dispose()
-        {
-            Dispose(true);
-        }
-        
-        ~UIViewControlHandle()
-        {
-            Dispose(false);
-        }
-        
-        private void Dispose(bool disposing)
-        {
-            if (_disposeView)
-            {
-                _view?.Dispose();
-            }
-
-            _view = null;
-            if (disposing)
-            {
-                GC.SuppressFinalize(this);
-            }
+            View.Dispose();
         }
     }
 }