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

使用WorkManager执行后台任务时UI仍冻结的问题排查求助

使用WorkManager执行后台任务时UI仍冻结的问题排查求助

我最近在用Flutter的workmanager库处理后台任务时碰到了个棘手的问题:当WorkManager调用callbackDispatcher的时候,App的UI会瞬间卡顿,要是任务里有重量级操作,卡顿还会持续。我试过用compute来处理重计算逻辑,能缓解后续的卡顿,但callbackDispatcher的初始调用还是会卡住UI,感觉这初始调用还是绑定在主isolate上,不像compute是在独立isolate里运行的。

我翻遍了各种资料都没找到解决办法,还特意在workmanager官方示例项目里加了CircularProgressIndicator测试,也自己写了个小Demo(就是下面的代码),结果都能复现这个问题。现在怀疑这个卡顿和我自己App里的audio_session有冲突,但也只是猜测。我大概率是哪里配置或者用法错了,真心想知道问题出在哪!


测试Demo代码

main.dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:xml/xml.dart';
import 'package:http/http.dart' as http;
import 'package:workmanager/workmanager.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  Workmanager().initialize(
    callbackDispatcher,
  );
  runApp(const MyApp());
}

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  int _counter = 0;

  void registerTask(bool useCompute) {
    Workmanager().cancelAll();
    Workmanager().registerOneOffTask(
      'backgroundTask',
      'backgroundTask',
      initialDelay: const Duration(seconds: 2),
      existingWorkPolicy: ExistingWorkPolicy.replace,
      inputData: {
        'useCompute': useCompute
      }
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () => registerTask(false),
              child: Text('Task without compute'),
            ),
            ElevatedButton(
              onPressed: () => registerTask(true),
              child: Text('Task with compute'),
            ),
            CircularProgressIndicator(),
          ],
        ),
      ),
    );
  }
}

@pragma('vm:entry-point')
void callbackDispatcher() async {
  Workmanager().executeTask((task, inputData) async {
    final useCompute = inputData?['useCompute'] ?? false;
    if(useCompute) {
      compute<Map<String, dynamic>, void>(updateTask, inputData ?? {});
      return true;
    } else {
      await updateTask(inputData ?? {});
      return true;//Future.value(true);
    }
  });
}

updateTask(Map<String, dynamic> value) async {
  try{
    print('Start debug task');
    final url = r'https://feeds.libsyn.com/583795/rss?limit=10';
    final uri = Uri.parse(url);
    print('Create Response');
    final request = http.Request('GET', uri)..maxRedirects = 20;
    request.followRedirects = false;
    final response = await http.Client().send(request);
    final location = response.headers['location'];
    // snapShot = log('Check feed URL', stopwatch, snapShot);
    print('Http get');
    //final feedContent = await http.get(uri);
    final feedContent = await http.get(uri);
    // snapShot = log('Feed url get', stopwatch, snapShot);
    final decodedContent = Utf8Decoder().convert(feedContent.bodyBytes);
    //print('No XML');
    print('XML Parse');
    final feedDoc = XmlDocument.parse(decodedContent);
    // snapShot = log('Xml parse', stopwatch, snapShot);
    final parentNode = feedDoc.findElements('rss')
        .single.findElements('channel').single;
    print('Get title');
    final title = _getNodeValue(parentNode, 'title', 'Title Not Found');
    print(title);
  } catch (e) {
    print(e);
  }
  print('End debug task');
}

String _getNodeValue(XmlElement parentNode, String nodeName, String backup) {
  try {
    var node = parentNode.findElements(nodeName);
    if (node.isNotEmpty) {
      var nodeText = node.first.innerText;
      return nodeText;
    } else return backup;
  } catch (_) {
    return backup;
  }
}

pubspec.yaml

name: test_project
description: "A new Flutter project."
publish_to: 'none'
version: 1.0.0+1

environment:
  sdk: ^3.8.1

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.8
  xml: ^6.5.0
  http: ^1.4.0
  workmanager: ^0.8.0

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^5.0.0

flutter:
  uses-material-design: true

flutter doctor 输出

[√] Flutter (Channel stable, 3.32.7, on Microsoft Windows [Version 10.0.26100.4652], locale en-US)
[√] Windows Version (11 Home 64-bit, 24H2, 2009)
[√] Android toolchain - develop for Android devices (Android SDK version 35.0.0)
[√] Chrome - develop for the web
[X] Visual

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:18:11