Browse Source

refactor(splash): 重构启动流程为并行任务并优化状态管理

将资源加载状态拆分为多个独立任务状态,包括追踪权限、版本检查、Token验证和应用配置
优化启动流程为并行执行,在1.5秒动画期间完成所有任务
添加任务完成状态检查确保所有任务完成后才进行页面跳转
weicu
lxm 1 year ago
parent
commit
dbb81cd8f7
  1. 156
      lib/modules/splash/controllers/splash_controller.dart

156
lib/modules/splash/controllers/splash_controller.dart

@ -24,9 +24,16 @@ class SplashController extends GetxController {
final _loadingProgress = 0.0.obs; final _loadingProgress = 0.0.obs;
double get loadingProgress => _loadingProgress.value; double get loadingProgress => _loadingProgress.value;
// 资源加载状态 // 各项任务完成状态
final _isResourceLoaded = false.obs; final _isTrackingPermissionRequested = false.obs; // 追踪权限请求完成
bool get isResourceLoaded => _isResourceLoaded.value; final _isVersionCheckCompleted = false.obs; // 版本检查完成
final _isTokenValidated = false.obs; // Token验证完成
final _isAppConfigLoaded = false.obs; // 应用配置加载完成
final _isAnimationCompleted = false.obs; // 动画完成
// 登录状态
final _isLoggedIn = false.obs;
bool get isLoggedIn => _isLoggedIn.value;
final _hasAcceptedPrivacy = false.obs; //是否同意隐私政策 final _hasAcceptedPrivacy = false.obs; //是否同意隐私政策
@ -59,38 +66,45 @@ class SplashController extends GetxController {
} }
}); });
// 异步处理用户追踪授权,不阻塞主流程 // 注意:追踪权限请求将在用户同意隐私政策后执行
_requestTrackingPermissionAsync();
} }
/// 异步请求追踪权限,不阻塞启动流程 /// 异步请求追踪权限
void _requestTrackingPermissionAsync() { Future<void> _requestTrackingPermissionAsync() async {
Future.delayed(const Duration(milliseconds: 500), () async { try {
try { await AppTrackingTransparency.requestTrackingAuthorization();
await AppTrackingTransparency.requestTrackingAuthorization(); Logger.d(_tag, '用户追踪权限请求完成');
Logger.d(_tag, '用户追踪权限请求完成'); } catch (e) {
} catch (e) { Logger.e(_tag, '用户追踪权限请求失败: $e');
Logger.e(_tag, '用户追踪权限请求失败: $e'); } finally {
} _isTrackingPermissionRequested.value = true;
}); }
} }
void _startNormalFlow() { void _startNormalFlow() {
_startLoadingAnimation(); _startLoadingAnimation();
_loadAppResources(); _startParallelTasks();
} }
/// 智能调度版本检查,在页面跳转后执行,完全不影响启动流程 /// 启动并行任务:在1.5秒动画期间同时执行多个任务
void _scheduleVersionCheck() { void _startParallelTasks() {
// 在独立的微任务中执行,避免阻塞主线程 // 并行执行所有任务
scheduleMicrotask(() async { _requestTrackingPermissionAsync();
try { _performVersionCheckAsync();
Logger.d(_tag, '开始执行版本检查(后台任务)'); _validateTokenAsync();
_checkVersionUpdateIfNeeded(); }
} catch (e) {
Logger.e(_tag, '版本检查调度失败: $e'); /// 异步执行版本检查
} Future<void> _performVersionCheckAsync() async {
}); try {
Logger.d(_tag, '开始执行版本检查');
await _checkVersionUpdateIfNeeded();
} catch (e) {
Logger.e(_tag, '版本检查失败: $e');
}
//finally {
// _isVersionCheckCompleted.value = true;
// }
} }
void _onPrivacyAccepted() { void _onPrivacyAccepted() {
@ -115,10 +129,10 @@ class SplashController extends GetxController {
); );
} }
// 进度条动画(持续2秒) // 进度条动画(持续1.5秒)
void _startLoadingAnimation() { void _startLoadingAnimation() {
const totalDuration = 1500; // 动画总时长增加到1.5秒 const totalDuration = 1500; // 动画总时长1.5秒
const steps = totalDuration ~/ 30; // 30的间隔,更平滑的动画 const steps = totalDuration ~/ 30; // 30ms间隔,更平滑的动画
const stepValue = 1.0 / steps; const stepValue = 1.0 / steps;
Timer.periodic(const Duration(milliseconds: 30), (timer) { Timer.periodic(const Duration(milliseconds: 30), (timer) {
@ -126,54 +140,53 @@ class SplashController extends GetxController {
_loadingProgress.value += stepValue; _loadingProgress.value += stepValue;
} else { } else {
timer.cancel(); timer.cancel();
_isAnimationCompleted.value = true;
_checkNavigateCondition(); _checkNavigateCondition();
} }
}); });
} }
// 异步加载应用资源 /// 异步验证Token和加载应用配置
Future<void> _loadAppResources() async { Future<void> _validateTokenAsync() async {
try { try {
// 模拟资源加载(如API配置、本地缓存等) bool isLoggedIn = false;
await Future.delayed(const Duration(milliseconds: 1500)); final token = _storage.read('logintoken');
Logger.d(_tag, 'Token验证开始: $token');
// 实际资源加载代码
// await _loadImages(); if (token != null && token.isNotEmpty) {
// await _initDatabase(); isLoggedIn = await getLoginToken();
if (isLoggedIn) {
await getAppConfig();
_isAppConfigLoaded.value = true;
}
}
_isResourceLoaded.value = true; _isLoggedIn.value = isLoggedIn;
_checkNavigateCondition(); Logger.d(_tag, 'Token验证完成,登录状态: $isLoggedIn');
} catch (e) { } catch (e) {
Get.snackbar('错误', '资源加载失败,请检查网络连接'); Logger.e(_tag, 'Token验证失败: $e');
_isResourceLoaded.value = true; // 允许用户继续使用 _isLoggedIn.value = false;
Logger.e(_tag, '资源加载错误: $e'); } finally {
_isTokenValidated.value = true;
} }
} }
// 检查跳转条件 // 检查跳转条件:所有任务都完成后才跳转
void _checkNavigateCondition() async { void _checkNavigateCondition() {
if (_loadingProgress.value >= 1.0 && _isResourceLoaded.value) { if (_isAnimationCompleted.value &&
// 关键改动:先执行页面跳转,并用 await 等待它完成 _isTrackingPermissionRequested.value &&
await _navigateToLogin(); _isVersionCheckCompleted.value &&
_isTokenValidated.value) {
// 页面跳转完全结束后,再安心地安排版本检查 _navigateToTargetPage();
_scheduleVersionCheck();
} }
} }
// 获取登录Token并跳转 // 根据登录状态跳转到目标页面
Future<void> _navigateToLogin() async { void _navigateToTargetPage() {
bool isLoggedIn = false; if (_isLoggedIn.value && _isAppConfigLoaded.value) {
final token = _storage.read('logintoken');
Logger.d(_tag, 'getLoginToken:进来了${token}');
if (token != null && token.isNotEmpty) {
isLoggedIn = await getLoginToken();
}
if (isLoggedIn) {
await getAppConfig();
Get.offAllNamed(Routes.pairing); Get.offAllNamed(Routes.pairing);
} else { } else {
Get.offAllNamed(Routes.login); // 跳转到登录页 Get.offAllNamed(Routes.login);
} }
} }
@ -227,7 +240,7 @@ class SplashController extends GetxController {
/// 混合检查机制:判断是否需要进行版本检查 /// 混合检查机制:判断是否需要进行版本检查
/// 检查条件:1. 会话内未检查过 OR 2. 距离上次检查超过24小时 /// 检查条件:1. 会话内未检查过 OR 2. 距离上次检查超过24小时
void _checkVersionUpdateIfNeeded() { Future<void> _checkVersionUpdateIfNeeded() async {
try { try {
final now = DateTime.now(); final now = DateTime.now();
final lastCheckTimestamp = _storage.read(_lastVersionCheckKey); final lastCheckTimestamp = _storage.read(_lastVersionCheckKey);
@ -259,7 +272,7 @@ class SplashController extends GetxController {
if (shouldCheck) { if (shouldCheck) {
Logger.i(_tag, '开始版本检查 - 原因: $reason'); Logger.i(_tag, '开始版本检查 - 原因: $reason');
_performVersionCheck(); await _performVersionCheck();
} else { } else {
Logger.i(_tag, '跳过版本检查 - 会话内已检查且未超过时间间隔'); Logger.i(_tag, '跳过版本检查 - 会话内已检查且未超过时间间隔');
} }
@ -278,9 +291,14 @@ class SplashController extends GetxController {
Logger.i(_tag, '发现新版本: ${updateInfo.latestVersion}'); Logger.i(_tag, '发现新版本: ${updateInfo.latestVersion}');
// 在主线程中显示更新对话框 // 在主线程中显示更新对话框
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
VersionUpdateDialog.show(updateInfo); VersionUpdateDialog.show(updateInfo).then((_) {
// 无论用户选择更新还是稍后提醒,都标记版本检查完成
_isVersionCheckCompleted.value = true;
_checkNavigateCondition();
});
}); });
} else { } else {
_isVersionCheckCompleted.value = true;
Logger.i(_tag, '当前已是最新版本: ${updateInfo.currentVersion}'); Logger.i(_tag, '当前已是最新版本: ${updateInfo.currentVersion}');
} }
@ -288,12 +306,16 @@ class SplashController extends GetxController {
_updateVersionCheckRecord(); _updateVersionCheckRecord();
}).catchError((e) { }).catchError((e) {
Logger.e(_tag, '版本检查失败: $e'); Logger.e(_tag, '版本检查失败: $e');
// 即使检查失败,也更新记录,避免频繁重试 // 即使检查失败,也标记版本检查完成,让流程继续
_isVersionCheckCompleted.value = true;
// 更新检查记录,避免频繁重试
_updateVersionCheckRecord(); _updateVersionCheckRecord();
}); });
} catch (e) { } catch (e) {
Logger.e(_tag, '版本检查失败: $e'); Logger.e(_tag, '版本检查失败: $e');
// 即使检查失败,也更新记录,避免频繁重试 // 即使检查失败,也标记版本检查完成,让流程继续
_isVersionCheckCompleted.value = true;
// 更新检查记录,避免频繁重试
_updateVersionCheckRecord(); _updateVersionCheckRecord();
} }
} }

Loading…
Cancel
Save