😋 初始化仓库
This commit is contained in:
275
lib/services/app_initialization_service.dart
Normal file
275
lib/services/app_initialization_service.dart
Normal file
@@ -0,0 +1,275 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import '../providers/auth_provider.dart';
|
||||
import '../services/notification_service.dart';
|
||||
import '../services/storage_service.dart';
|
||||
import '../utils/session_manager.dart';
|
||||
|
||||
/// Service for handling app initialization tasks
|
||||
///
|
||||
/// Coordinates initialization of various services and providers:
|
||||
/// - Theme preferences loading
|
||||
/// - Notification service setup
|
||||
/// - Session restoration
|
||||
/// - Cache management
|
||||
///
|
||||
/// Usage example:
|
||||
/// ```dart
|
||||
/// final initService = AppInitializationService(
|
||||
/// authProvider: authProvider,
|
||||
/// themeProvider: themeProvider,
|
||||
/// notificationService: notificationService,
|
||||
/// );
|
||||
///
|
||||
/// final result = await initService.initialize();
|
||||
/// if (result.success) {
|
||||
/// // App initialized successfully
|
||||
/// }
|
||||
/// ```
|
||||
class AppInitializationService {
|
||||
final AuthProvider _authProvider;
|
||||
final NotificationService _notificationService;
|
||||
final StorageService _storageService;
|
||||
late final SessionManager _sessionManager;
|
||||
|
||||
AppInitializationService({
|
||||
required AuthProvider authProvider,
|
||||
required NotificationService notificationService,
|
||||
StorageService? storageService,
|
||||
}) : _authProvider = authProvider,
|
||||
_notificationService = notificationService,
|
||||
_storageService = storageService ?? StorageService() {
|
||||
_sessionManager = SessionManager(authProvider: _authProvider);
|
||||
}
|
||||
|
||||
/// Initialize the application
|
||||
///
|
||||
/// Performs all necessary initialization tasks in the correct order
|
||||
/// Returns InitializationResult with status and details
|
||||
Future<InitializationResult> initialize() async {
|
||||
final startTime = DateTime.now();
|
||||
final steps = <InitializationStep>[];
|
||||
|
||||
try {
|
||||
// Step 1: Initialize notification service
|
||||
steps.add(await _initializeNotifications());
|
||||
|
||||
// Step 2: Load theme preferences
|
||||
steps.add(await _loadThemePreferences());
|
||||
|
||||
// Step 3: Check and manage cache
|
||||
steps.add(await _manageCacheVersion());
|
||||
|
||||
// Step 4: Attempt session restoration
|
||||
steps.add(await _restoreSession());
|
||||
|
||||
final duration = DateTime.now().difference(startTime);
|
||||
final allSuccessful = steps.every((step) => step.success);
|
||||
|
||||
return InitializationResult(
|
||||
success: allSuccessful,
|
||||
steps: steps,
|
||||
duration: duration,
|
||||
sessionRestored: steps
|
||||
.firstWhere(
|
||||
(s) => s.name == 'Session Restoration',
|
||||
orElse: () => InitializationStep(
|
||||
name: 'Session Restoration',
|
||||
success: false,
|
||||
),
|
||||
)
|
||||
.success,
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Error during app initialization: $e');
|
||||
final duration = DateTime.now().difference(startTime);
|
||||
|
||||
return InitializationResult(
|
||||
success: false,
|
||||
steps: steps,
|
||||
duration: duration,
|
||||
error: e.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize notification service
|
||||
Future<InitializationStep> _initializeNotifications() async {
|
||||
try {
|
||||
await _notificationService.initialize();
|
||||
return InitializationStep(
|
||||
name: 'Notification Service',
|
||||
success: true,
|
||||
message: 'Notification service initialized',
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Failed to initialize notifications: $e');
|
||||
return InitializationStep(
|
||||
name: 'Notification Service',
|
||||
success: false,
|
||||
message: 'Failed to initialize notifications: $e',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Load theme preferences
|
||||
Future<InitializationStep> _loadThemePreferences() async {
|
||||
try {
|
||||
// Theme preferences are loaded in ThemeProvider constructor
|
||||
// This step just confirms it's ready
|
||||
return InitializationStep(
|
||||
name: 'Theme Preferences',
|
||||
success: true,
|
||||
message: 'Theme preferences loaded',
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Failed to load theme preferences: $e');
|
||||
return InitializationStep(
|
||||
name: 'Theme Preferences',
|
||||
success: false,
|
||||
message: 'Failed to load theme preferences: $e',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Manage cache version
|
||||
Future<InitializationStep> _manageCacheVersion() async {
|
||||
try {
|
||||
const expectedCacheVersion = 1; // Update this when data structure changes
|
||||
final cleared = await _storageService.clearCacheIfVersionMismatch(
|
||||
expectedCacheVersion,
|
||||
);
|
||||
|
||||
if (cleared) {
|
||||
return InitializationStep(
|
||||
name: 'Cache Management',
|
||||
success: true,
|
||||
message: 'Cache cleared due to version mismatch',
|
||||
);
|
||||
} else {
|
||||
return InitializationStep(
|
||||
name: 'Cache Management',
|
||||
success: true,
|
||||
message: 'Cache version is current',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Failed to manage cache: $e');
|
||||
return InitializationStep(
|
||||
name: 'Cache Management',
|
||||
success: false,
|
||||
message: 'Failed to manage cache: $e',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempt to restore previous session
|
||||
Future<InitializationStep> _restoreSession() async {
|
||||
try {
|
||||
// Check if session can be restored
|
||||
final canRestore = await _sessionManager.canRestoreSession();
|
||||
|
||||
if (!canRestore) {
|
||||
return InitializationStep(
|
||||
name: 'Session Restoration',
|
||||
success: false,
|
||||
message: 'No saved session to restore',
|
||||
);
|
||||
}
|
||||
|
||||
// Attempt restoration
|
||||
final result = await _sessionManager.restoreSession();
|
||||
|
||||
if (result.success) {
|
||||
return InitializationStep(
|
||||
name: 'Session Restoration',
|
||||
success: true,
|
||||
message: 'Session restored successfully',
|
||||
);
|
||||
} else {
|
||||
// Session restoration failed, but this is not a critical error
|
||||
// User will just need to login again
|
||||
return InitializationStep(
|
||||
name: 'Session Restoration',
|
||||
success: false,
|
||||
message: result.message,
|
||||
reason: result.reason,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('Error during session restoration: $e');
|
||||
return InitializationStep(
|
||||
name: 'Session Restoration',
|
||||
success: false,
|
||||
message: 'Session restoration error: $e',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Get session manager instance
|
||||
SessionManager get sessionManager => _sessionManager;
|
||||
|
||||
/// Get storage service instance
|
||||
StorageService get storageService => _storageService;
|
||||
}
|
||||
|
||||
/// Result of app initialization
|
||||
class InitializationResult {
|
||||
final bool success;
|
||||
final List<InitializationStep> steps;
|
||||
final Duration duration;
|
||||
final bool sessionRestored;
|
||||
final String? error;
|
||||
|
||||
InitializationResult({
|
||||
required this.success,
|
||||
required this.steps,
|
||||
required this.duration,
|
||||
this.sessionRestored = false,
|
||||
this.error,
|
||||
});
|
||||
|
||||
/// Get failed steps
|
||||
List<InitializationStep> get failedSteps =>
|
||||
steps.where((step) => !step.success).toList();
|
||||
|
||||
/// Get successful steps
|
||||
List<InitializationStep> get successfulSteps =>
|
||||
steps.where((step) => step.success).toList();
|
||||
|
||||
/// Check if initialization is complete (even with some non-critical failures)
|
||||
bool get isComplete => steps.isNotEmpty;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InitializationResult('
|
||||
'success: $success, '
|
||||
'sessionRestored: $sessionRestored, '
|
||||
'steps: ${steps.length}, '
|
||||
'duration: ${duration.inMilliseconds}ms'
|
||||
')';
|
||||
}
|
||||
}
|
||||
|
||||
/// Individual initialization step
|
||||
class InitializationStep {
|
||||
final String name;
|
||||
final bool success;
|
||||
final String? message;
|
||||
final SessionRestoreFailureReason? reason;
|
||||
|
||||
InitializationStep({
|
||||
required this.name,
|
||||
required this.success,
|
||||
this.message,
|
||||
this.reason,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InitializationStep('
|
||||
'name: $name, '
|
||||
'success: $success, '
|
||||
'message: $message'
|
||||
')';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user