You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在MAUI中注册兼容PageRenderer引发堆栈溢出异常

在MAUI中复用Xamarin.Forms的PageRenderer时出现堆栈溢出异常

迁移MAUI应用后,尝试复用Xamarin.Forms项目中的现有PageRenderer,页面加载时触发堆栈溢出异常,调用栈如下:

0x39 in Java.Interop.NativeMethods.java_interop_jnienv_call_nonvirtual_void_method_a C#
0x74 in Java.Interop.JniEnvironment.InstanceMethods.CallNonvirtualVoidMethod at /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/obj/Release/net7.0/JniEnvironment.g.cs:12320,4 C#
0x2D in Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeNonvirtualVoidMethod at /Users/runner/work/1/s/xamarin-android/external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.JniInstanceMethods_Invoke.cs:93,6 C#
0x69 in Android.Views.ViewGroup.Layout at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/obj/Release/net7.0/android-33/mcw/Android.Views.ViewGroup.cs:3369,5 C#
0xD4 in Microsoft.Maui.ViewHandlerExtensions.PlatformArrangeHandler at D:\a_work\1\s\src\Core\src\Handlers\ViewHandlerExtensions.Android.cs:133,4 C#
0x2 in Microsoft.Maui.Handlers.ViewHandler<Microsoft.Maui.IView,Android.Views.View>.PlatformArrange at D:\a_work\1\s\src\Core\src\Handlers\View\ViewHandlerOfT.Android.cs:15,4 C#
0x37 in Microsoft.Maui.Controls.Compatibility.RendererToHandlerShim.PlatformArrange at D:\a_work\1\s\src\Compatibility\Core\src\RendererToHandlerShim.Android.cs:51,4 C#
0x1F in Microsoft.Maui.Controls.ContentPage.ArrangeOverride at D:\a_work\1\s\src\Controls\src\Core\HandlerImpl\ContentPage.Impl.cs:22,4 C#
0x2 in Microsoft.Maui.Controls.VisualElement.Microsoft.Maui.IView.Arrange at D:\a_work\1\s\src\Controls\src\Core\HandlerImpl\VisualElement\VisualElement.Impl.cs:111,4 C#
0x4F in Microsoft.Maui.Controls.Compatibility.Platform.Android.PageRenderer.OnLayout at D:\a_work\1\s\src\Compatibility\Core\src\Android\Renderers\PageRenderer.cs:169,4 C#
0x10 in Microsoft.Maui.MauiViewGroup.n_OnLayout_ZIIII at D:\a_work\1\s\src\Core\src\obj\Release\net7.0-android\generated\src\Microsoft.Maui.MauiViewGroup.cs:206,4 C#
0x11 in Android.Runtime.JNINativeWrapper.Wrap_JniMarshal_PPZIIII_V at /Users/runner/work/1/s/xamarin-android/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs:429,5 C#

即使注释掉渲染器中的业务代码,问题依然存在。当前使用的渲染器代码如下:

using Android.Content;
using System;
using Microsoft.Maui.Controls.Platform;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Compatibility.Platform.Android;
using PetActivityMobile.Core;
using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;

namespace PetActivityMobile.Droid.Renderers
{
    public class CreateAccountViewRenderer : PageRenderer
    {
        private bool _initialized;
        private Page _page;

        public CreateAccountViewRenderer(Context context) : base(context)
        {

        }

        protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
            if (!_initialized && e?.NewElement != null)
            {
                _initialized = true;
                _page = e.NewElement;

                //The appearing event invoke before OnElementChanged called.
                //So I'm changing the keyboard behavior also here for the first time when page up.
                App.Current.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Pan);

                _page.Appearing -= OnAppearing;
                _page.Appearing += OnAppearing;
                _page.Disappearing -= OnDisappearing;
                _page.Disappearing += OnDisappearing;
            }
        }

        protected override void OnDetachedFromWindow()
        {
            _page.Appearing -= OnAppearing;
            _page.Disappearing -= OnDisappearing;
            _initialized = false;
        }

        private void OnAppearing(object sender, EventArgs e)
        {
            App.Current.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Pan);
        }

        private void OnDisappearing(object sender, EventArgs e)
        {
            App.Current.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
        }
    }
}

在Android项目中注册渲染器的方式如下:

private void RegisterRenderers(MauiAppBuilder mauiApp)
{
    mauiApp.ConfigureMauiHandlers((handlers) =>
    {
        handlers.AddCompatibilityRenderer(typeof(MyEntry), typeof(MyRenderer));
        handlers.AddCompatibilityRenderer(typeof(CreateAccountView), typeof(CreateAccountViewRenderer));
    });
}

其中Entry的渲染器可以正常工作,想问有没有人尝试过在MAUI中复用Xamarin.Forms的PageRenderer?


解决方案

  1. 放弃直接继承PageRenderer:MAUI的兼容性渲染器机制对Page类型的处理存在递归布局调用问题,直接复用Xamarin.Forms的PageRenderer会触发OnLayout和Arrange的循环调用,导致堆栈溢出。
  2. 改用MAUI原生方式处理需求:针对页面的软键盘调整需求,无需使用渲染器,直接在页面代码后台实现:
    protected override void OnAppearing()
    {
        base.OnAppearing();
        App.Current.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>()
            .UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Pan);
    }
    
    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        App.Current.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>()
            .UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
    }
    
  3. 移除PageRenderer的兼容性注册:删除handlers.AddCompatibilityRenderer(typeof(CreateAccountView), typeof(CreateAccountViewRenderer));这一行,避免与MAUI原生布局流程冲突。
  4. 检查页面布局:确认CreateAccountView页面的布局是否存在嵌套过深或约束错误,这类问题会加重堆栈溢出的触发概率。

原因分析

MAUI的RendererToHandlerShim会将旧的Xamarin.Forms渲染器适配为MAUI的Handler,但Page类型的布局流程在MAUI中已重构,PageRenderer的OnLayout方法会触发MAUI的PlatformArrange,而后者又会回调到OnLayout,形成无限递归,最终导致堆栈溢出。Entry等控件的渲染器无此问题,是因为它们的布局逻辑不存在这种递归触发链。

内容的提问来源于stack exchange,提问作者o_w

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:34:51