You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过WorkManager修改TaskProvider中的任务列表?

问题分析

WorkManager的回调运行在独立的后台隔离进程,和主APP进程完全分离:你在后台新建的TaskProvider实例,和UI层依赖的实例不是同一个对象,后台修改的只是独立内存中的数据,自然无法同步到主进程的UI。

可行解决方案

核心思路是通过持久化存储共享任务数据,后台直接修改磁盘数据,主进程监听数据变化或在合适时机同步更新。

步骤1:给TaskProvider添加持久化逻辑

用shared_preferences(或Hive、SQLite)将任务列表持久化到磁盘,确保前后台数据一致。首先给TaskModel实现序列化/反序列化:

enum TaskStatus { pending, completed }

class TaskModel {
  final String task;
  final DateTime limitDateTime;
  final TaskStatus status;

  TaskModel({
    required this.task,
    required this.limitDateTime,
    required this.status,
  });

  // 转JSON用于存储
  Map<String, dynamic> toJson() => {
        'task': task,
        'limitDateTime': limitDateTime.toIso8601String(),
        'status': status.name,
      };

  // 从JSON解析
  factory TaskModel.fromJson(Map<String, dynamic> json) => TaskModel(
        task: json['task'],
        limitDateTime: DateTime.parse(json['limitDateTime']),
        status: TaskStatus.values.byName(json['status']),
      );
}

修改TaskProvider,整合持久化逻辑:

import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';

class TaskProvider extends ChangeNotifier {
  final List<TaskModel> _tasks = [];
  final String _tasksKey = "tasks";
  final SharedPreferences _prefs;

  // 构造函数注入SharedPreferences
  TaskProvider(this._prefs) {
    _loadTasks();
  }

  List<TaskModel> get tasks => _tasks;

  // 从磁盘加载任务
  Future<void> _loadTasks() async {
    final String? tasksJson = _prefs.getString(_tasksKey);
    if (tasksJson != null) {
      final List<dynamic> decoded = jsonDecode(tasksJson);
      _tasks.clear();
      _tasks.addAll(decoded.map((e) => TaskModel.fromJson(e)).toList());
      notifyListeners();
    }
  }

  // 保存任务到磁盘
  Future<void> _saveTasks() async {
    final String tasksJson = jsonEncode(_tasks.map((e) => e.toJson()).toList());
    await _prefs.setString(_tasksKey, tasksJson);
  }

  Future<void> addTask({
    required String task,
    required DateTime scheduledTime,
    required TaskStatus status,
  }) async {
    scheduleTaskManager(task, scheduledTime);
    _tasks.add(TaskModel(task: task, limitDateTime: scheduledTime, status: status));
    await _saveTasks();
    notifyListeners();
  }

  Future<void> clearTasks() async {
    dev.log("Tasks deleted!");
    _tasks.clear();
    await _saveTasks();
    notifyListeners();
  }
}

步骤2:修改WorkManager回调,直接操作持久化存储

后台不需要实例化TaskProvider,直接修改磁盘上的任务数据:

import 'package:shared_preferences/shared_preferences.dart';

@pragma('vm:entry-point')
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    dev.log("Native called background task: $task");
    dev.log("Time limit, clearing all tasks!");
    
    // 直接清除磁盘中的任务数据
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.remove("tasks");
    
    return Future.value(true);
  });
}

步骤3:主进程同步数据更新

有两种方式让主进程感知后台的数据变化:

方式1:APP回到前台时自动刷新

通过监听APP生命周期,在回到前台时重新加载任务:

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  late TaskProvider _taskProvider;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _taskProvider = Provider.of<TaskProvider>(context, listen: false);
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    // APP回到前台时重新加载任务
    if (state == AppLifecycleState.resumed) {
      _taskProvider._loadTasks();
    }
  }

  @override
  Widget build(BuildContext context) {
    // 你的UI代码...
  }
}

方式2:跨进程通信实时更新

如果需要后台修改后立刻更新UI,用MethodChannel实现前后台通信:

  1. 主进程初始化MethodChannel并监听消息:
import 'package:flutter/services.dart';

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  static const platform = MethodChannel('com.yourpackage/task_updates');
  late TaskProvider _taskProvider;

  @override
  void initState() {
    super.initState();
    _taskProvider = Provider.of<TaskProvider>(context, listen: false);
    // 监听后台发送的更新消息
    platform.setMethodCallHandler((call) async {
      if (call.method == 'tasksCleared') {
        await _taskProvider._loadTasks();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(/* ... */);
  }
}
  1. 后台任务完成后发送消息:
import 'package:flutter/services.dart';

@pragma('vm:entry-point')
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    dev.log("Native called background task: $task");
    dev.log("Time limit, clearing all tasks!");
    
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    await prefs.remove("tasks");

    // 发送消息通知主进程更新
    const platform = MethodChannel('com.yourpackage/task_updates');
    try {
      await platform.invokeMethod('tasksCleared');
    } on PlatformException catch (e) {
      dev.log("Failed to send update: ${e.message}");
    }
    
    return Future.value(true);
  });
}

内容的提问来源于stack exchange,提问作者Yasuki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:33:28