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

.NET MAUI中AppShell ViewModel无法留存用户数据的求助

解决.NET MAUI Flyout休眠唤醒后用户信息丢失问题

核心问题在于内存中的UserInfo数据会在应用休眠时被系统回收,仅依赖单例ViewModel无法持久化数据。以下是具体解决方案:

1. 持久化用户信息

登录成功后将用户数据序列化存储到本地,注销时清除。可根据数据敏感程度选择:

  • Preferences:存储非敏感数据(如用户名、头像URL)
  • SecureStorage:存储敏感数据(如用户ID、令牌)

示例代码(登录成功时):

// 序列化用户对象
var userJson = System.Text.Json.JsonSerializer.Serialize(currentUser);
// 存储到Preferences
Preferences.Set("CurrentAuthenticatedUser", userJson);
// 敏感数据用SecureStorage
// await SecureStorage.SetAsync("CurrentAuthenticatedUser", userJson);

2. 修改AppShellViewModel

在ViewModel中添加持久化逻辑,确保初始化、应用唤醒时都能加载用户信息:

public partial class AppShellViewModel : BaseViewModel, IDisposable
{
    public AppShellViewModel()
    {
        // 初始化时先加载本地存储的用户信息
        LoadUserFromStorage();
        
        MessagingCenter.Subscribe<User>(this, "userUpdated", (user) => {
            UserInfo = user;
            // 收到更新后同步持久化
            SaveUserToStorage(user);
        });
        
        // 订阅应用唤醒事件
        Application.Current.Resumed += OnAppResumed;
    }

    [ObservableProperty]
    User userInfo;

    [RelayCommand]
    async Task SignOff()
    {
        // 注销时清除本地存储
        Preferences.Remove("CurrentAuthenticatedUser");
        // await SecureStorage.RemoveAsync("CurrentAuthenticatedUser");
        UserInfo = null;
        
        // 执行其他注销逻辑(如跳转登录页)
    }

    private void LoadUserFromStorage()
    {
        var userJson = Preferences.Get("CurrentAuthenticatedUser", string.Empty);
        // var userJson = await SecureStorage.GetAsync("CurrentAuthenticatedUser");
        
        if (!string.IsNullOrEmpty(userJson))
        {
            UserInfo = System.Text.Json.JsonSerializer.Deserialize<User>(userJson);
        }
    }

    private void SaveUserToStorage(User user)
    {
        var userJson = System.Text.Json.JsonSerializer.Serialize(user);
        Preferences.Set("CurrentAuthenticatedUser", userJson);
        // await SecureStorage.SetAsync("CurrentAuthenticatedUser", userJson);
    }

    private void OnAppResumed(object sender, EventArgs e)
    {
        // 应用唤醒时重新加载用户信息
        LoadUserFromStorage();
    }

    // 清理事件订阅,避免内存泄漏
    public void Dispose()
    {
        Application.Current.Resumed -= OnAppResumed;
        MessagingCenter.Unsubscribe<User>(this, "userUpdated");
    }
}

3. 清理ViewModel订阅

在AppShell中实现ViewModel的资源释放:

public partial class AppShell : Shell
{
    private readonly AppShellViewModel _viewModel;

    public AppShell(AppShellViewModel viewModel)
    {
        InitializeComponent();
        _viewModel = viewModel;
        BindingContext = _viewModel;
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();
        _viewModel.Dispose();
    }
}

4. 确保User类可序列化

给User类添加可序列化标识,或确保所有属性都是基础可序列化类型:

[Serializable]
public class User
{
    public string Name { get; set; }
    public string AvatarUrl { get; set; }
    // 其他属性
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 20:48:23