如何在isolate/FlutterBackgroundService中保留变量值?

问题描述 投票:0回答:1

我目前正在努力在

Flutter
中实现带有通知处理程序的隔离。

它已经在工作了,我有一个

MQTT
侦听器,它使用
AwesomeNotification
显示通知,并有 2 个用于接受或拒绝通知的操作。

当接受通知时,我想进行 API 调用来更新与该通知相关的记录。

为了让我变得更简单,我在

MQTT
有效负载中包含了一些详细信息,我需要使用这些详细信息来进行 API 调用,我将该详细信息设置为一个变量,以便稍后使用它。

问题是,当应用程序到达

AwesomeNotification's onActionReceivedMethod
时,变量的值已经消失了。

我认为这样做的原因是因为,执行代码已经超出了

service/isolate
的范围,因此无法访问该变量。

然后我尝试使用

SharedPreferences
,但密钥的更新速度没有我想要/预期的那么快。现在,我不知道如何保留一点价值,以便我可以继续这个过程。

这是我当前的代码:

import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:isolate';
import 'dart:ui';

import 'package:baraco_frontend/helpers/api/request_vehicle_change_api_helper.dart';
import 'package:baraco_frontend/helpers/sharedPref/shared_pref_helper.dart';
import 'package:flutter/material.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
import 'package:intl/intl.dart';
import 'package:mqtt_client/mqtt_client.dart';
import 'package:vibration/vibration.dart';
import 'package:awesome_notifications/awesome_notifications.dart';

import '../globals.dart';
import '../models/user.dart';
import 'mqtt_helper.dart';

final _service = FlutterBackgroundService();
String notifTxt = 'Waiting for notification';
const String approveKey = 'approve';
const String rejectKey = 'reject';
const String approveLabel = 'Approve';
const String rejectLabel = 'Reject';
String _requestVehicleChangeId = '';
ReceivePort processRequestVehicleChangeRecvPort = ReceivePort('processRequestVehicleChangeRecv');

Future<void> initializeService() async{
  log('initializeService');
  await _service.configure(
    androidConfiguration: AndroidConfiguration(
      autoStart: true,
      onStart: _onServiceStart,
      isForegroundMode: true,
    ),
    iosConfiguration: IosConfiguration(
      autoStart: true,
      onForeground: _onServiceStart,
      onBackground: _onServiceIosBackground,
    ),
  );

  await initializeLocalNotifications();
  await initializeIsolateReceivePort();
  startListeningNotificationEvents();
}

@pragma('vm:entry-point')
Future<void> _onServiceStart(ServiceInstance service) async {
  DartPluginRegistrant.ensureInitialized();
  log('service started');

  if (service is AndroidServiceInstance) {
    service.on('setAsForeground').listen((ev) {
      service.setAsForegroundService();
    });
    service.on('setAsBackground').listen((ev) {
      service.setAsBackgroundService();
    });
  }

  service.on('stopService').listen((ev) {
    service.stopSelf();
  });

  MqttHelper().connect().then((val) async {
    var user = User.fromJson( jsonDecode(await SharedPrefHelper().getPrefWithKey( Globals.USER_PREF_KEY )) );

    MqttHelper().send('hi from the app', user.mqttClientId);
    MqttHelper().subscribe(user.mqttClientId);
  });

  Timer(const Duration(milliseconds: 1000), () {
    MqttHelper().getClient().updates!.listen((List<MqttReceivedMessage<MqttMessage?>>? c) async {
      final recMessage = c![0].payload as MqttPublishMessage;
      final payload = MqttPublishPayload.bytesToStringAsString(recMessage.payload.message);
      var payloadArr = payload.split(':');
      log('payloadArr: $payloadArr');
      notifTxt = payloadArr[0];
      _requestVehicleChangeId = payloadArr[1];
      
      // _requestVehicleChangeId surely has value here
      

      showNotification('BARACO Notification', notifTxt);
      Vibration.vibrate(pattern: [0,
        550, 100,
        550, 100,
        550, 100,
        550, 100,
        200, 50,
        200, 50,
        200, 50,
        200, 190, 700]);
    });
  });
}

@pragma('vm:entry-point')
Future<bool> _onServiceIosBackground(ServiceInstance service) async{
  WidgetsFlutterBinding.ensureInitialized();
  DartPluginRegistrant.ensureInitialized();
  log('onServiceIosBackground started');
  return false;
}

Future<void> initializeLocalNotifications() async {
  await AwesomeNotifications().initialize(
    null,
    [
    NotificationChannel(
      channelKey: 'alerts',
      channelName: 'Alerts',
      channelDescription: 'Notification tests as alerts',
      playSound: true,
      onlyAlertOnce: true,
      importance: NotificationImportance.High,
      defaultPrivacy: NotificationPrivacy.Private,
      defaultColor: Colors.deepPurple,
      ledColor: Colors.deepPurple
    )
    ],
    debug: true
  );
}

ReceivePort? receivePort;
Future<void> initializeIsolateReceivePort() async {
  receivePort = ReceivePort('Notification action port in main isolate')
  ..listen(
    (silentData) {
      onActionReceived(silentData);
    }
  );

  IsolateNameServer.registerPortWithName(
  receivePort!.sendPort, 'notification_action_port');
  log('initializeIsolateReceivePort');
}

Future<void> startListeningNotificationEvents() async {
  AwesomeNotifications()
    .setListeners(onActionReceivedMethod: onActionReceived);
}

@pragma('vm:entry-point')
Future<void> onActionReceived(ReceivedAction receivedAction) async {
    // _requestVehicleChangeId has no value now here
    // this is where I wanted to do the api calls
  
}

@pragma('vm:entry-point')
Future<void> showNotification(String title, String body) async {
  // _requestVehicleChangeId still has value here

  bool isAllowed = await AwesomeNotifications().isNotificationAllowed();

  await AwesomeNotifications().createNotification(
      content: NotificationContent(
          id: -1,
          channelKey: 'alerts',
          title: title,
          body: body,
          bigPicture: '',
          largeIcon: '',
          notificationLayout: NotificationLayout.BigPicture,
          payload: {'notificationId': '1234567890'}),
      actionButtons: [
        NotificationActionButton(
            key: rejectKey,
            label: rejectLabel,
            actionType: ActionType.SilentAction,
            isDangerousOption: true),
        NotificationActionButton(
            key: approveKey,
            label: approveLabel,
            actionType: ActionType.SilentAction)
      ]
  );
}

更新:

我刚刚意识到

AwesomeNotification
有一个名为
content
的有效负载字段,其中有一个名为
payload
的字段,它似乎接受
Map
但即使在他们自己的回调中,你似乎也无法访问它。这些例子用一些东西填充了
payload
,但没有被使用。多么奇怪啊。

flutter dart dart-isolates awesome-notifications
1个回答
0
投票

经过一番探索,我发现传递给

ReceivedAction
onActionReceivedMethod
实际上包含
NotificationContent
作为
Map
,解决了我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.