Flutter后台进程中SharedPreferences返回null问题求助
问题描述
我使用flutter_background_service插件实现应用后台图片处理功能,处理所需的参数已提前存入SharedPreferences,但在processImage方法中,获取SharedPreferences实例并执行reload后,所有参数均返回null,只能使用默认值。
相关代码
初始化后台服务代码
Future<void> initializeService() async { final service = FlutterBackgroundService(); // 创建Android通知渠道 const AndroidNotificationChannel channel = AndroidNotificationChannel( notificationChannelId, // ID 'IMAGE STAMPING SERVICE', // 标题 description: '此渠道用于重要通知', importance: Importance.high, // 设置重要性 ); final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); // 创建通知渠道 await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); await service.configure( androidConfiguration: AndroidConfiguration( onStart: onStart, autoStart: true, isForegroundMode: true, notificationChannelId: notificationChannelId, initialNotificationTitle: '图片盖章服务', initialNotificationContent: '初始化中', foregroundServiceNotificationId: notificationId, ), iosConfiguration: IosConfiguration( autoStart: true, onForeground: onStart, ), ); } /// 初始化图片目录监听器 void initializePhotoWatcher() async { try { // 初始化SharedPreferences SharedPreferences prefs = await SharedPreferences.getInstance(); // 获取权限状态 bool arePermissionsGranted = prefs.getBool('permissionsGranted') ?? false; if (arePermissionsGranted) { photoDirectory = Directory(AppConstants.directoryPath); if (await photoDirectory?.exists() ?? false) { final watcher = DirectoryWatcher(photoDirectory!.path); print("已为路径创建目录监听器: ${photoDirectory!.path}"); watcher.events.listen((event) { print("检测到事件: ${event.toString()}"); if (event.type == ChangeType.ADD && !event.path.contains("stamped_") && !event.path.contains(".pending")) { print("调度文件处理: ${event.path}"); // 调用后台服务 final service = FlutterBackgroundService(); service.invoke('processImage', {'imagePath': event.path}); } }); } else { print("相机目录不存在或无法访问"); } } else { // 请求权限并等待授权 bool permissionsGranted = await requestPermissions(); if (permissionsGranted) { // 权限已授权,继续初始化 photoDirectory = Directory(AppConstants.directoryPath); // 剩余代码... } else { // 权限未授权,进行相应处理 print("需要更多权限"); } } } catch (e) { print(e.toString()); } } Future<void> onStart(ServiceInstance service) async { // DartPluginRegistrant.ensureInitialized(); // final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = // FlutterLocalNotificationsPlugin(); // 设置前后台状态切换监听 if (service is AndroidServiceInstance) { service.on('processImage').listen((data) { final String imagePath = data?['imagePath']; service.setAsBackgroundService(); // 执行图片处理 processImage(imagePath); }); service.on('setAsForeground').listen((event) { service.setAsForegroundService(); }); service.on('setAsBackground').listen((event) { service.setAsBackgroundService(); }); } service.on('stopService').listen((event) { service.stopSelf(); }); }
图片处理代码
void processImage(String imagePath) async { try { final File imageFile = File(imagePath); final SharedPreferences prefs = await SharedPreferences.getInstance(); // 按其他方案建议执行重载 await prefs.reload(); // 获取用户偏好设置 // 所有参数都返回null,只能使用默认值 int fontSize = prefs.getInt('fontSize') ?? AppConstants.fontSize; int scaledFontSize = fontSize * 2; final Color fontColor = _getFontColorFromString(prefs); // 获取文本位置 String textPositionString = prefs.getString('textPlacement') ?? AppConstants.textPosition.name; TextPosition textPosition = TextPosition.values.firstWhere( (e) => e.name == textPositionString, orElse: () => AppConstants.textPosition // 未找到时使用默认值 ); String text = prefs.getString('text') ?? AppConstants.text; // 检查文件是否存在且不是临时文件 if (await imageFile.exists() && !imageFile.path.contains('.pending-')) { // 调用图片盖章函数 await addStampToPhoto( image: imageFile, fontSize: scaledFontSize, text: text, fontColor: fontColor, textPosition: textPosition, photoDirectoryPath: AppConstants.directoryPath, ); } else { // 记录日志并处理,比如稍后重试 print('文件不存在或为临时文件: $imagePath'); } } catch (e) { print('处理文件 $imagePath 时出错: $e'); // 可选:实现重试机制或其他错误处理 } }
解决方案
1. 初始化Dart插件注册器
后台服务运行在独立的Isolate中,必须初始化插件注册器才能正确访问SharedPreferences。取消onStart方法中相关注释:
Future<void> onStart(ServiceInstance service) async { DartPluginRegistrant.ensureInitialized(); // 必须添加此行 // ... 剩余代码 }
2. 直接传递参数到后台服务(替代方案)
如果初始化注册器后问题仍存在,可以在调用服务时直接传递所需参数,避免在后台读取SharedPreferences:
// 在initializePhotoWatcher的事件监听中,先获取参数再传递 watcher.events.listen((event) { print("检测到事件: ${event.toString()}"); if (event.type == ChangeType.ADD && !event.path.contains("stamped_") && !event.path.contains(".pending")) { print("调度文件处理: ${event.path}"); // 先获取SharedPreferences中的参数 SharedPreferences.getInstance().then((prefs) { int fontSize = prefs.getInt('fontSize') ?? AppConstants.fontSize; String textPositionString = prefs.getString('textPlacement') ?? AppConstants.textPosition.name; String text = prefs.getString('text') ?? AppConstants.text; // 传递所有需要的参数 final service = FlutterBackgroundService(); service.invoke('processImage', { 'imagePath': event.path, 'fontSize': fontSize, 'textPlacement': textPositionString, 'text': text, // 其他需要的参数(如字体颜色) }); }); } });
修改onStart方法接收参数:
service.on('processImage').listen((data) { final String imagePath = data?['imagePath']; final int fontSize = data?['fontSize'] ?? AppConstants.fontSize; final String textPositionString = data?['textPlacement'] ?? AppConstants.textPosition.name; final String text = data?['text'] ?? AppConstants.text; service.setAsBackgroundService(); // 直接传递参数给processImage processImage(imagePath, fontSize, textPositionString, text); });
更新processImage方法接收参数:
void processImage(String imagePath, int fontSize, String textPositionString, String text) async { try { final File imageFile = File(imagePath); int scaledFontSize = fontSize * 2; // 直接使用传递的参数,无需再读取SharedPreferences final Color fontColor = // 若需字体颜色,同样在invoke时传递参数 TextPosition textPosition = TextPosition.values.firstWhere( (e) => e.name == textPositionString, orElse: () => AppConstants.textPosition ); // ... 后续处理代码 } catch (e) { print('处理文件 $imagePath 时出错: $e'); } }
3. 检查SharedPreferences存储时机
确保参数在后台服务启动前已完成写入,且存储操作是异步完成的,避免后台服务读取时数据尚未持久化。
内容的提问来源于stack exchange,提问作者who-aditya-nawandar
相关产品推荐
相关产品推荐

