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

.NET MAUI中如何在App类获取MainActivity实例并解决空值问题

解决方案:MAUI中App类获取屏幕宽高避免MainActivity.Instance为空的问题

方案1:使用MAUI原生跨平台API(推荐)

MAUI提供了DeviceDisplay API直接获取屏幕信息,无需依赖Android原生的MainActivity,完全跨平台,且从根源上避免了启动顺序问题。

修改App类中的ScreenWidth属性:

public int ScreenWidth
{
    get
    {
        var displayInfo = DeviceDisplay.Current.MainDisplayInfo;
        // 将物理像素转换为独立像素(与Android的DisplayMetrics逻辑一致)
        return (int)(displayInfo.Width / displayInfo.Density);
    }
}

注意事项

  • DeviceDisplay.Current.MainDisplayInfo在App启动初期(如构造函数)可能无法获取有效数据,建议在页面加载完成后再调用该属性,或者用懒加载延迟初始化:
    private int? _lazyScreenWidth;
    public int ScreenWidth
    {
        get
        {
            if (!_lazyScreenWidth.HasValue)
            {
                var displayInfo = DeviceDisplay.Current.MainDisplayInfo;
                _lazyScreenWidth = (int)(displayInfo.Width / displayInfo.Density);
            }
            return _lazyScreenWidth.Value;
        }
    }
    

方案2:调整原生依赖的获取时机(仅Android平台)

如果必须依赖MainActivity,需要确保在MainActivity初始化完成后再获取实例,同时优化实例的生命周期管理:

步骤1:完善MainActivity的实例管理

在MainActivity中添加销毁时的实例清空逻辑,避免内存泄漏:

public class MainActivity : global::Microsoft.Maui.MauiAppCompatActivity
{
    internal static MainActivity Instance { get; private set; }

    protected override void OnCreate(Bundle savedInstanceState)
    {
        try
        {
            base.OnCreate(savedInstanceState);
            Instance = this; // 将实例赋值放在base.OnCreate之后,确保MAUI初始化完成
        }
        catch (Exception ex)
        {
            ExceptionLogger.LogErrorAsync(ex);
        }
    }

    protected override void OnDestroy()
    {
        base.OnDestroy();
        Instance = null; // 页面销毁时清空实例,避免内存泄漏
    }
}

步骤2:延迟在App的OnStart方法中初始化屏幕宽高

App.OnStart方法会在页面启动后执行,此时MainActivity已完成初始化:

public partial class App : Application
{
    private int? _screenWidth;

    protected override void OnStart()
    {
        base.OnStart();
        if (MainActivity.Instance != null)
        {
            var metrics = MainActivity.Instance.Resources.DisplayMetrics;
            _screenWidth = Convert.ToInt32(metrics.WidthPixels / metrics.Density);
        }
    }

    public int ScreenWidth
    {
        get
        {
            if (_screenWidth.HasValue)
                return _screenWidth.Value;
            // 根据业务需求返回默认值或抛出异常
            throw new InvalidOperationException("屏幕宽高未初始化,请在App启动完成后调用");
        }
    }
}

方案3:依赖注入+平台特定服务(解耦设计)

通过依赖注入封装屏幕信息服务,实现平台代码与业务逻辑的解耦:

步骤1:定义跨平台接口

public interface IScreenInfoService
{
    int GetScreenWidth();
}

步骤2:Android平台实现

public class AndroidScreenInfoService : IScreenInfoService
{
    public int GetScreenWidth()
    {
        if (MainActivity.Instance == null)
            throw new InvalidOperationException("MainActivity尚未初始化");
        
        var metrics = MainActivity.Instance.Resources.DisplayMetrics;
        return Convert.ToInt32(metrics.WidthPixels / metrics.Density);
    }
}

步骤3:注册服务

在MainApplication的CreateMauiApp方法中注册平台服务:

protected override MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder.UseMauiApp<App>()
           .UseMauiCommunityToolkit();
    
    // 注册平台特定服务
    builder.Services.AddSingleton<IScreenInfoService, AndroidScreenInfoService>();

    return builder.Build();
}

步骤4:在App中注入并使用

public partial class App : Application
{
    private readonly IScreenInfoService _screenInfoService;

    // 通过构造函数注入服务
    public App(IScreenInfoService screenInfoService)
    {
        InitializeComponent();
        _screenInfoService = screenInfoService;
        MainPage = new MainPage();
    }

    public int ScreenWidth => _screenInfoService.GetScreenWidth();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:18:42