首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何知道背景隔离中是否存在主隔离

如何知道背景隔离中是否存在主隔离
EN

Stack Overflow用户
提问于 2021-11-15 14:54:43
回答 1查看 170关注 0票数 0

我使用工作经理包启动后台任务,并与主隔离进行通信。

main.dart中,我的代码如下:

代码语言:javascript
复制
Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // call Workmanager().initialize()
  await BackgroundService().init();
  // init ReceivePort
  var port = ReceivePort();
  if (IsolateNameServer.lookupPortByName('bChannel') != null)
    IsolateNameServer.removePortNameMapping('bChannel');
  IsolateNameServer.registerPortWithName(port.sendPort, 'bChannel');
  port.listen((dynamic data) async {
    print('[Main][bChannel listener] got $data');
    // send http request and update ui
  });
  BackgroundService().registerPeriodicTask();
  print('[Main] init');
  runApp(MyApp());
}

background_service.dart中,我的代码如下:

代码语言:javascript
复制
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    try {
      switch (task) {
        case 'a':
          print("[Background] Task A triggered.");
          var sendPort = IsolateNameServer.lookupPortByName('bChannel');
          if (sendPort != null) {
            sendPort.send('message from background');
            print("[Background] message sent.");
          } else {
            print("[Background] no send port.");
            // send http request in background and save result to SharedPreferences
            final SharedPreferences prefs = await SharedPreferences.getInstance();
            await prefs.setString('result', 'result_message');
          }
          print("[Background] Task A finished.");
          break;
      }
      return Future.value(true);
    } catch (e) {
      print("[Background] $e");
      return Future.value(false);
    }
  });
}

class BackgroundService {
  // singleton things
  static final BackgroundService _instance = BackgroundService._internal();

  factory BackgroundService() {
    return _instance;
  }

  BackgroundService._internal() ;

  void registerWeatherRefreshPeriodicTask() {
    Workmanager().registerPeriodicTask(
      'TaskA',
      'TaskA',
      initialDelay: Duration(minutes: 1),
      frequency: Duration(minutes: 15),
      constraints: Constraints(
        networkType: NetworkType.connected
      )
    );
  }

  Future init() async {
    Workmanager().initialize(
      callbackDispatcher,
      isInDebugMode: true,
    );
  }

}

当应用程序在前面和后台运行时,它可以工作。但是,如果该应用程序退出(回击)到Android上,我会看到类似的日志

代码语言:javascript
复制
I/flutter ( 8342): [Main] init
D/FlutterLocationService( 8342): Unbinding from location service.
D/FlutterLocationService( 8342): Destroying service.
I/flutter ( 8342): [Background] Task A triggered.
I/flutter ( 8342): [Background] no send port.
I/flutter ( 8342): [Background] Task A finished.

没有日志可以指示主隔离程序使用消息。来自ReceivePort文档

ReceivePort是一种非广播流.这意味着它会缓冲传入的消息,直到注册侦听器为止。

当我再次打开这个应用程序时,它会再次显示[Main] init。因此,我想主要的隔离已经退出,并且没有侦听器到端口。

我想做的是:

  • 当应用程序在前面运行时,后台任务触发并最终更新UI。
  • 当应用程序运行在“后台”(UI退出但背景实际上正在运行)时,后台任务触发并发送http请求并保存结果。因此,当应用程序再次启动时,它可以读取结果并呈现UI。

我怎样才能实现这一点呢?

EN

回答 1

Stack Overflow用户

发布于 2021-11-28 04:56:25

我放弃了触发主隔离来呈现,而不是后台隔离更新和保存结果,并让主隔离重新呈现,如果它正在运行,否则在初始化期间呈现。

main.dart

代码语言:javascript
复制
Future main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // call Workmanager().initialize()
  await BackgroundService().init();
  // init ReceivePort
  var port = ReceivePort();
  if (IsolateNameServer.lookupPortByName('bChannel') != null)
    IsolateNameServer.removePortNameMapping('bChannel');
  IsolateNameServer.registerPortWithName(port.sendPort, 'bChannel');
  port.listen((dynamic data) async {
    print('[Main][bChannel listener] got $data');
    // refresh shared preferences and trigger render
    final prefs = await SharedPreferences.getInstance();
    await prefs.reload(); // reload otherwise it will use out-dated data
    // add BLoC event
    bloc.add(refreshEvent());
  });
  BackgroundService().registerPeriodicTask();
  print('[Main] init');
  runApp(MyApp());
}

background_service.dart

代码语言:javascript
复制
void callbackDispatcher() {
  Workmanager().executeTask((task, inputData) async {
    try {
      // also init and reload shared preferences
      // if main isolate contains other initialization works, it should also put here
      final SharedPreferences prefs = await SharedPreferences.getInstance();
      await prefs.reload();
      var httpClient = http.Client();

      switch (task) {
        case 'a':
          print("[Background] Task A triggered.");
          // send http request and save the result
          var response = await httpClient.get(uri);
          await prefs.setString('result', response.body);

          var sendPort = IsolateNameServer.lookupPortByName('bChannel');
          if (sendPort != null) {
            sendPort.send('message from background');
            print("[Background] message sent.");
          }
          print("[Background] Task A finished.");
          break;
      }
      return Future.value(true);
    } catch (e) {
      print("[Background] $e");
      return Future.value(false);
    }
  });
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69976389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档