Starward项目米游社工具箱角色删除后自动刷新问题分析

Starward项目米游社工具箱角色删除后自动刷新问题分析

【免费下载链接】Starward Game Launcher for miHoYo - 米家游戏启动器 【免费下载链接】Starward 项目地址: https://gitcode.com/gh_mirrors/st/Starward

痛点场景:角色管理中的刷新困境

在使用Starward米游社工具箱时,许多用户都遇到过这样的困扰:当删除某个游戏角色后,界面数据没有及时更新,需要手动刷新才能看到变化。这种体验上的不连贯性影响了工具箱的整体使用流畅度。本文将深入分析Starward项目中角色删除后的自动刷新机制,探讨问题根源并提供解决方案。

技术架构概览

Starward的米游社工具箱采用MVVM(Model-View-ViewModel)架构,结合消息传递机制实现数据同步。核心组件包括:

核心类关系图

mermaid

删除流程详细分析

1. 界面层删除操作

GameRecordPage.xaml.cs中,删除角色的核心代码如下:

private void MenuFlyoutItem_DeleteGameRole_Click(object sender, RoutedEventArgs e)
{
    GameRecordRole? gameRole = null;
    try
    {
        if (sender is FrameworkElement { Tag: GameRecordRole role })
        {
            gameRole = role;
            _gameRecordService.DeleteGameRole(role);
            LoadGameRoles();
        }
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Delete game role ({gameBiz}, {uid}).", gameRole?.GameBiz, gameRole?.Uid);
    }
}

2. 服务层数据处理

GameRecordService.cs中的删除逻辑:

public bool DeleteGameRole(GameRecordRole role)
{
    bool deletedUser = false;
    using var dapper = DatabaseService.CreateConnection();
    using var t = dapper.BeginTransaction();
    dapper.Execute("DELETE FROM GameRecordRole WHERE GameBiz = @GameBiz AND Uid = @Uid;", role, t);
    _logger.LogInformation("Deleted game roles with ({nickname}, {gameBiz}, {uid}).", role.Nickname, role.GameBiz, role.Uid);
    
    if (dapper.QueryFirstOrDefault<int>("SELECT Count(*) FROM GameRecordRole WHERE Cookie = @Cookie;", role, t) == 0)
    {
        dapper.Execute("DELETE FROM GameRecordUser WHERE Cookie = @Cookie;", role, t);
        _logger.LogInformation("Deleted all relative accounts of ({nickname}, {gameBiz}, {uid})", role.Nickname, role.GameBiz, role.Uid);
        deletedUser = true;
    }
    t.Commit();
    return deletedUser;
}

3. 数据重新加载机制

删除后的刷新操作:

private void LoadGameRoles(GameRecordRole? role = null)
{
    try
    {
        if (role != null)
        {
            _gameRecordService.SetLastSelectGameRecordRole(CurrentGameBiz, role);
        }
        role ??= _gameRecordService.GetLastSelectGameRecordRoleOrTheFirstOne(CurrentGameBiz);
        var list = _gameRecordService.GetGameRoles(CurrentGameBiz);
        CurrentRole = role ?? list.FirstOrDefault();
        GameRoleList = list;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Load game roles ({gameBiz}).", CurrentGameBiz);
    }
}

问题诊断与根本原因

1. 消息传递机制缺失

当前实现中,删除操作后仅调用了LoadGameRoles()方法,但没有发送相应的消息通知:

// 缺失的消息发送代码
WeakReferenceMessenger.Default.Send(new GameRecordRoleChangedMessage(null));

2. 状态同步不完整

虽然LoadGameRoles()方法会重新加载角色列表,但可能存在以下问题:

问题类型具体表现影响范围
界面状态不同步当前选中角色未正确重置单页面内
消息未广播其他组件不知道角色变化跨组件通信
缓存未清理内存缓存中仍存在已删除数据性能问题

3. 异常处理不完善

当前的异常处理虽然记录了错误,但没有提供用户友好的反馈机制:

catch (Exception ex)
{
    _logger.LogError(ex, "Delete game role ({gameBiz}, {uid}).", gameRole?.GameBiz, gameRole?.Uid);
    // 缺少用户提示
}

解决方案与优化建议

1. 完善消息传递机制

在删除操作后添加消息广播:

private void MenuFlyoutItem_DeleteGameRole_Click(object sender, RoutedEventArgs e)
{
    GameRecordRole? gameRole = null;
    try
    {
        if (sender is FrameworkElement { Tag: GameRecordRole role })
        {
            gameRole = role;
            bool deletedUser = _gameRecordService.DeleteGameRole(role);
            
            // 发送角色变化消息
            WeakReferenceMessenger.Default.Send(new GameRecordRoleChangedMessage(null));
            
            LoadGameRoles();
            
            // 提供用户反馈
            InAppToast.MainWindow?.Success(Lang.HoyolabToolboxPage_RoleDeleted);
        }
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Delete game role ({gameBiz}, {uid}).", gameRole?.GameBiz, gameRole?.Uid);
        InAppToast.MainWindow?.Error(Lang.HoyolabToolboxPage_DeleteRoleFailed);
    }
}

2. 增强状态管理

改进LoadGameRoles方法,确保状态完全重置:

private void LoadGameRoles(GameRecordRole? role = null)
{
    try
    {
        var list = _gameRecordService.GetGameRoles(CurrentGameBiz);
        
        // 如果当前角色已被删除,重置为第一个可用角色
        if (CurrentRole != null && !list.Any(r => r.Uid == CurrentRole.Uid))
        {
            CurrentRole = list.FirstOrDefault();
        }
        else if (role != null)
        {
            CurrentRole = role;
            _gameRecordService.SetLastSelectGameRecordRole(CurrentGameBiz, role);
        }
        else
        {
            CurrentRole ??= _gameRecordService.GetLastSelectGameRecordRoleOrTheFirstOne(CurrentGameBiz);
        }
        
        GameRoleList = list;
        
        // 通知界面更新
        OnPropertyChanged(nameof(CurrentRole));
        OnPropertyChanged(nameof(GameRoleList));
        OnPropertyChanged(nameof(AvatarUrl));
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Load game roles ({gameBiz}).", CurrentGameBiz);
    }
}

3. 添加缓存清理机制

在服务层添加缓存清理逻辑:

public bool DeleteGameRole(GameRecordRole role)
{
    bool deletedUser = false;
    using var dapper = DatabaseService.CreateConnection();
    using var t = dapper.BeginTransaction();
    
    // 删除数据库记录
    dapper.Execute("DELETE FROM GameRecordRole WHERE GameBiz = @GameBiz AND Uid = @Uid;", role, t);
    
    // 清理内存缓存
    string cacheKey = $"game_role_{role.GameBiz}_{role.Uid}";
    _memoryCache.Remove(cacheKey);
    
    _logger.LogInformation("Deleted game roles with ({nickname}, {gameBiz}, {uid}).", role.Nickname, role.GameBiz, role.Uid);
    
    if (dapper.QueryFirstOrDefault<int>("SELECT Count(*) FROM GameRecordRole WHERE Cookie = @Cookie;", role, t) == 0)
    {
        dapper.Execute("DELETE FROM GameRecordUser WHERE Cookie = @Cookie;", role, t);
        _logger.LogInformation("Deleted all relative accounts of ({nickname}, {gameBiz}, {uid})", role.Nickname, role.GameBiz, role.Uid);
        deletedUser = true;
    }
    t.Commit();
    return deletedUser;
}

测试验证方案

1. 单元测试用例

[Test]
public async Task DeleteGameRole_Should_RefreshUI_Automatically()
{
    // 准备测试数据
    var testRole = new GameRecordRole { Uid = 123456, GameBiz = GameBiz.hk4e_cn };
    var mockService = new Mock<IGameRecordService>();
    var messenger = new WeakReferenceMessenger();
    
    // 设置mock
    mockService.Setup(s => s.DeleteGameRole(It.IsAny<GameRecordRole>())).Returns(true);
    mockService.Setup(s => s.GetGameRoles(It.IsAny<GameBiz>())).Returns(new List<GameRecordRole>());
    
    // 执行删除操作
    var page = new GameRecordPage(mockService.Object, messenger);
    page.DeleteGameRole(testRole);
    
    // 验证消息发送
    Assert.IsTrue(messenger.IsRegistered<GameRecordRoleChangedMessage>());
    
    // 验证界面状态
    Assert.IsNull(page.CurrentRole);
    Assert.IsEmpty(page.GameRoleList);
}

2. 集成测试场景

测试场景预期结果验证方法
删除当前选中角色界面自动切换到其他角色UI状态检查
删除唯一角色界面显示无角色状态空状态验证
并发删除操作数据一致性保持线程安全测试

性能优化建议

1. 批量操作支持

public int DeleteGameRoles(IEnumerable<GameRecordRole> roles)
{
    int deletedCount = 0;
    using var dapper = DatabaseService.CreateConnection();
    using var t = dapper.BeginTransaction();
    
    foreach (var role in roles)
    {
        dapper.Execute("DELETE FROM GameRecordRole WHERE GameBiz = @GameBiz AND Uid = @Uid;", role, t);
        deletedCount++;
        
        // 清理缓存
        string cacheKey = $"game_role_{role.GameBiz}_{role.Uid}";
        _memoryCache.Remove(cacheKey);
    }
    
    t.Commit();
    return deletedCount;
}

2. 异步处理优化

public async Task<bool> DeleteGameRoleAsync(GameRecordRole role)
{
    return await Task.Run(() => DeleteGameRole(role));
}

总结与展望

Starward项目的米游社工具箱在角色删除后的自动刷新问题上,主要存在消息传递机制不完善、状态同步不完整、缓存清理不彻底等问题。通过完善消息广播、增强状态管理、添加缓存清理等优化措施,可以显著提升用户体验。

未来的改进方向包括:

  1. 实时数据同步:引入WebSocket实现实时数据更新
  2. 离线操作支持:完善离线模式下的数据一致性
  3. 智能缓存策略:基于LRU算法的智能缓存管理
  4. 用户体验优化:添加删除确认和撤销功能

通过系统性的架构优化和细节完善,Starward项目的米游社工具箱将能够为用户提供更加流畅、稳定的角色管理体验。

【免费下载链接】Starward Game Launcher for miHoYo - 米家游戏启动器 【免费下载链接】Starward 项目地址: https://gitcode.com/gh_mirrors/st/Starward

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值