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

如何在MAUI中通过依赖注入复用弹窗?

解决.NET MAUI中通过依赖注入复用弹窗的问题

问题根源

MAUI Community Toolkit的MauiPopup在关闭时会被框架自动调用Dispose()方法释放资源,同一个弹窗实例无法被重复展示——这就是你遇到Cannot access a disposed object错误的核心原因:不管是直接注入弹窗实例,还是封装成服务复用单一实例,第一次关闭后实例就已被释放,再次调用必然触发异常。

解决方案1:使用工厂模式注入弹窗创建逻辑

不要直接注入弹窗实例,而是注入一个能创建新弹窗的工厂,每次需要展示时生成全新实例:

1. 定义弹窗工厂接口与实现

public interface ILoadingPopupFactory
{
    LoadingControl CreateLoadingControl(string message);
}

public class LoadingPopupFactory : ILoadingPopupFactory
{
    public LoadingControl CreateLoadingControl(string message)
    {
        return new LoadingControl(message);
    }
}

2. 在MauiProgram中注册工厂

builder.Services.AddTransient<ILoadingPopupFactory, LoadingPopupFactory>();

3. 在ViewModel中使用工厂创建弹窗

修改TopicSelectionViewModel:

public IApiService ApiService { get; }
public IDatabaseRepository repository;
private readonly ILoadingPopupFactory _loadingPopupFactory;

public TopicSelectionViewModel(IApiService apiService, IDatabaseRepository _repo, ILoadingPopupFactory loadingPopupFactory)
{
    ApiService = apiService;
    repository = _repo;
    _loadingPopupFactory = loadingPopupFactory;
}

[RelayCommand]
async Task Download(Topic topic)
{
    if (topic is null) return;
    
    // 每次需要时创建新的弹窗实例
    var loadingControl = _loadingPopupFactory.CreateLoadingControl("Downloading your info...");
    Shell.Current.ShowPopup(loadingControl);

    if (ApiService.InternetAvailable())
    {
        try
        {
            await repository.SaveTopicAndQuestionsAsync(await ApiService.GetQuestionsAsync(topic.TopicRef), topic.TopicRef);
        }
        catch (Exception ex) 
        {
            Debug.WriteLine(ex);
            Debug.WriteLine(ex.InnerException?.Message ?? "No inner exception");
        }
        finally
        {
            Refresh();
            loadingControl.Close();
        }
    }
    else
    {
        await Shell.Current.DisplayAlert("No Internet", "Connect to the internet to download", "Ok");
        loadingControl.Close();
    }
}

解决方案2:改进LoadingService,每次展示创建新实例

如果偏好用服务封装弹窗逻辑,修改服务代码,每次调用ShowLoading时创建新实例,避免复用已释放的对象:

1. 修改ILoadingService与LoadingService

public interface ILoadingService
{
    void ShowLoading(string message);
    void CloseLoading();
}

public class LoadingService : ILoadingService
{
    private LoadingPopup _currentPopup;

    public void CloseLoading()
    {
        _currentPopup?.Close();
        // 关闭后清空引用,避免持有已释放的实例
        _currentPopup = null;
    }

    public void ShowLoading(string message)
    {
        // 每次展示都创建新的弹窗实例
        _currentPopup = new LoadingPopup(message);
        Shell.Current.ShowPopup(_currentPopup);
    }
}

2. 注册服务(瞬态或单例均可,因为每次都创建新实例)

builder.Services.AddSingleton<ILoadingService, LoadingService>();

3. 在ViewModel中使用服务

public IApiService ApiService { get; }
public IDatabaseRepository repository;
private readonly ILoadingService _loadingService;

public TopicSelectionViewModel(IApiService apiService, IDatabaseRepository _repo, ILoadingService loadingService)
{
    ApiService = apiService;
    repository = _repo;
    _loadingService = loadingService;
}

[RelayCommand]
async Task Download(Topic topic)
{
    if (topic is null) return;
    
    _loadingService.ShowLoading("Downloading your info...");

    if (ApiService.InternetAvailable())
    {
        try
        {
            await repository.SaveTopicAndQuestionsAsync(await ApiService.GetQuestionsAsync(topic.TopicRef), topic.TopicRef);
        }
        catch (Exception ex) 
        {
            Debug.WriteLine(ex);
            Debug.WriteLine(ex.InnerException?.Message ?? "No inner exception");
        }
        finally
        {
            Refresh();
            _loadingService.CloseLoading();
        }
    }
    else
    {
        await Shell.Current.DisplayAlert("No Internet", "Connect to the internet to download", "Ok");
        _loadingService.CloseLoading();
    }
}

关键注意事项

  • 绝对不要复用已关闭的弹窗实例,MAUI框架会在弹窗关闭后自动处置它
  • 通过工厂或每次创建新实例的方式,确保每次展示的都是未被释放的全新实例
  • 在异常分支或取消操作时,务必记得关闭弹窗,避免弹窗一直停留在界面上

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 20:10:50