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

Community Toolkit弹窗导致MAUI应用卡顿,如何解决?

问题修复与优化方案

针对MAUI Community Toolkit弹窗每次打开加载时长递增的问题,核心原因是每次新建弹窗时重复创建大量UI控件且未正确清理资源,导致内存累积、布局计算开销持续增加。以下是具体修复和规避方案:

1. 复用弹窗实例(最直接的优化)

不要每次点击都新建Popup1实例,而是在页面初始化时创建一次,后续重复使用:

修改主页面代码:

using CommunityToolkit.Maui.Views;

namespace MauiApp2;

public partial class MainPage : ContentPage
{
    private Popup1 _reusablePopup;

    public MainPage()
    {
        InitializeComponent();
        // 仅初始化一次弹窗
        _reusablePopup = new Popup1();
    }

    private void OnCounterClicked(object sender, EventArgs e)
    {
        // 复用已有弹窗实例
        this.ShowPopup(_reusablePopup);
    }
}

如果需要重置弹窗状态(比如更新加载时间),可以在弹窗的Closed事件中处理:

public Popup1()
{
    sw.Start();
    InitializeComponent();
    Size = new Size(350, 500);
    for (int i = 0; i < 100; i++)
        Flex.Add(new Button() { Text = i.ToString() });
    
    Opened += (_, _) => 
    {
        // 移除之前的加载时间标签,避免重复添加
        var oldLabel = Flex.Children.OfType<Label>().FirstOrDefault();
        if(oldLabel != null) Flex.Children.Remove(oldLabel);
        
        Flex.Add(new Label() { Text = sw.ElapsedMilliseconds.ToString() });
        sw.Restart(); // 重置计时器用于下次打开
    };
}

2. 使用数据绑定替代手动添加控件

手动循环添加100个Button会产生大量重复的控件初始化开销,改用CollectionView+数据绑定,利用控件复用机制提升性能:

弹窗XAML修改:

<?xml version="1.0" encoding="utf-8" ?>
<toolkit:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             x:Class="MauiApp2.Popup1">
    <VerticalStackLayout>
        <!-- 使用CollectionView复用控件模板 -->
        <CollectionView ItemsSource="{Binding ButtonTexts}" 
                        HeightRequest="450"
                        ItemsLayout="VerticalGrid, 3">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Button Text="{Binding}" Margin="2"/>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
        <Label x:Name="LoadTimeLabel" HorizontalOptions="Center"/>
    </VerticalStackLayout>
</toolkit:Popup>

弹窗后台代码修改:

using CommunityToolkit.Maui.Views;
using System.Collections.ObjectModel;
using System.Diagnostics;

namespace MauiApp2;

public partial class Popup1 : Popup
{
    Stopwatch sw = new();
    // 绑定数据源
    public ObservableCollection<string> ButtonTexts { get; set; } = new();

    public Popup1()
    {
        sw.Start();
        InitializeComponent();
        Size = new Size(350, 500);
        
        // 一次性初始化数据源
        for (int i = 0; i < 100; i++)
            ButtonTexts.Add(i.ToString());
        
        BindingContext = this;
        
        Opened += (_, _) => 
        {
            LoadTimeLabel.Text = sw.ElapsedMilliseconds.ToString();
            sw.Restart();
        };
    }
}

3. 确保弹窗资源正确清理(若必须新建实例)

如果业务场景要求每次新建弹窗,需在弹窗关闭时彻底清理资源,避免内存泄漏:

public Popup1()
{
    sw.Start();
    InitializeComponent();
    Size = new Size(350, 500);
    for (int i = 0; i < 100; i++)
        Flex.Add(new Button() { Text = i.ToString() });
    
    // 绑定Opened事件到单独方法,方便后续移除
    Opened += PopupOpened;
    // 绑定Closed事件用于清理
    Closed += PopupClosed;
}

private void PopupOpened(object? sender, EventArgs e)
{
    Flex.Add(new Label() { Text = sw.ElapsedMilliseconds.ToString() });
}

private void PopupClosed(object? sender, CommunityToolkit.Maui.Core.PopupClosedEventArgs e)
{
    // 移除事件绑定
    Opened -= PopupOpened;
    Closed -= PopupClosed;
    
    // 清空所有子控件
    Flex.Children.Clear();
    
    // 释放计时器资源
    sw.Stop();
    sw = null;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:23:16