From f12cc8a52c73d453d9bf55a4f5bd76f5092bf966 Mon Sep 17 00:00:00 2001 From: Emmanuel Hansen Date: Wed, 7 Aug 2024 12:19:07 +0000 Subject: [PATCH] android - defer rendering till surface is created --- .../Avalonia.Android/AvaloniaActivity.cs | 2 +- .../Avalonia.Android/AvaloniaMainActivity.cs | 2 +- src/Android/Avalonia.Android/AvaloniaView.cs | 20 +++++++++++++++++-- .../InvalidationAwareSurfaceView.cs | 11 +++++++++- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/Android/Avalonia.Android/AvaloniaActivity.cs b/src/Android/Avalonia.Android/AvaloniaActivity.cs index 71175957876..fa3484f0586 100644 --- a/src/Android/Avalonia.Android/AvaloniaActivity.cs +++ b/src/Android/Avalonia.Android/AvaloniaActivity.cs @@ -155,7 +155,7 @@ protected override void OnDestroy() base.OnDestroy(); } - + protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent? data) { base.OnActivityResult(requestCode, resultCode, data); diff --git a/src/Android/Avalonia.Android/AvaloniaMainActivity.cs b/src/Android/Avalonia.Android/AvaloniaMainActivity.cs index 639082ed02d..63097b22a1a 100644 --- a/src/Android/Avalonia.Android/AvaloniaMainActivity.cs +++ b/src/Android/Avalonia.Android/AvaloniaMainActivity.cs @@ -21,8 +21,8 @@ private protected override void InitializeAvaloniaView(object? initialContent) { initialContent ??= Lifetime.MainView; - Lifetime.Activity = this; _view = new AvaloniaView(this) { Content = initialContent }; + Lifetime.Activity = this; } else { diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs index aa5124dcea8..b5a4287fb05 100644 --- a/src/Android/Avalonia.Android/AvaloniaView.cs +++ b/src/Android/Avalonia.Android/AvaloniaView.cs @@ -21,6 +21,7 @@ public class AvaloniaView : FrameLayout private readonly ViewImpl _view; private IDisposable? _timerSubscription; + private bool _surfaceCreated; public AvaloniaView(Context context) : base(context) { @@ -32,6 +33,18 @@ public AvaloniaView(Context context) : base(context) this.SetBackgroundColor(global::Android.Graphics.Color.Transparent); OnConfigurationChanged(); + + _view.InternalView.SurfaceWindowCreated += InternalView_SurfaceWindowCreated; + } + + private void InternalView_SurfaceWindowCreated(object? sender, EventArgs e) + { + _surfaceCreated = true; + + if (Visibility == ViewStates.Visible) + { + OnVisibilityChanged(true); + } } internal TopLevelImpl TopLevelImpl => _view; @@ -43,9 +56,10 @@ public object? Content set { _root.Content = value; } } - protected override void Dispose(bool disposing) + internal new void Dispose() { - base.Dispose(disposing); + OnVisibilityChanged(false); + _surfaceCreated = false; _root?.Dispose(); _root = null!; } @@ -70,6 +84,8 @@ protected override void OnVisibilityChanged(View changedView, [GeneratedEnum] Vi internal void OnVisibilityChanged(bool isVisible) { + if (_root == null || !_surfaceCreated) + return; if (isVisible && _timerSubscription == null) { if (AvaloniaLocator.Current.GetService() is ChoreographerTimer timer) diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs index 0d9206f4181..2ec255df19a 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs @@ -13,9 +13,12 @@ namespace Avalonia.Android internal abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, INativePlatformHandleSurface { bool _invalidateQueued; + private bool _isDisposed; readonly object _lock = new object(); private readonly Handler _handler; + internal event EventHandler? SurfaceWindowCreated; + IntPtr IPlatformHandle.Handle => Holder?.Surface?.Handle is { } handle ? AndroidFramebuffer.ANativeWindow_fromSurface(JNIEnv.Handle, handle) : default; @@ -39,7 +42,7 @@ public override void Invalidate() return; _handler.Post(() => { - if (Holder?.Surface?.IsValid != true) + if (_isDisposed || Holder?.Surface?.IsValid != true) return; try { @@ -53,6 +56,11 @@ public override void Invalidate() } } + internal new void Dispose() + { + _isDisposed = true; + } + public void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height) { Log.Info("AVALONIA", "Surface Changed"); @@ -62,6 +70,7 @@ public void SurfaceChanged(ISurfaceHolder holder, Format format, int width, int public void SurfaceCreated(ISurfaceHolder holder) { Log.Info("AVALONIA", "Surface Created"); + SurfaceWindowCreated?.Invoke(this, EventArgs.Empty); DoDraw(); }