Starward项目米游社工具箱角色删除后自动刷新问题分析
【免费下载链接】Starward Game Launcher for miHoYo - 米家游戏启动器 项目地址: https://gitcode.com/gh_mirrors/st/Starward
痛点场景:角色管理中的刷新困境
在使用Starward米游社工具箱时,许多用户都遇到过这样的困扰:当删除某个游戏角色后,界面数据没有及时更新,需要手动刷新才能看到变化。这种体验上的不连贯性影响了工具箱的整体使用流畅度。本文将深入分析Starward项目中角色删除后的自动刷新机制,探讨问题根源并提供解决方案。
技术架构概览
Starward的米游社工具箱采用MVVM(Model-View-ViewModel)架构,结合消息传递机制实现数据同步。核心组件包括:
核心类关系图
删除流程详细分析
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项目的米游社工具箱在角色删除后的自动刷新问题上,主要存在消息传递机制不完善、状态同步不完整、缓存清理不彻底等问题。通过完善消息广播、增强状态管理、添加缓存清理等优化措施,可以显著提升用户体验。
未来的改进方向包括:
- 实时数据同步:引入WebSocket实现实时数据更新
- 离线操作支持:完善离线模式下的数据一致性
- 智能缓存策略:基于LRU算法的智能缓存管理
- 用户体验优化:添加删除确认和撤销功能
通过系统性的架构优化和细节完善,Starward项目的米游社工具箱将能够为用户提供更加流畅、稳定的角色管理体验。
【免费下载链接】Starward Game Launcher for miHoYo - 米家游戏启动器 项目地址: https://gitcode.com/gh_mirrors/st/Starward
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



