Flutter中如何从后台服务的WebSocket获取流数据到主应用程序?

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

我正在开发一个 Flutter 项目,其中使用后台服务(带有 flutter_background_service 包)来处理 WebSocket 连接。即使应用程序位于后台,WebSocket 也会收到更新。我的目标是将后台服务中接收到的 WebSocket 数据流式传输到主应用程序,以便 UI 可以实时更新。


final service = FlutterBackgroundService();

Future<void> initializeService() async {
  await service.configure(
    iosConfiguration: IosConfiguration(
        autoStart: true, onForeground: onStart, onBackground: onBackground),
    androidConfiguration: AndroidConfiguration(
        autoStartOnBoot: false,
        onStart: onStart,
        isForegroundMode: true,
        autoStart: false),
  );
}

IO.Socket? socket;

void connectWebSocket(String uniqueId) {
  const String serverUrl = 'http://test.buggyhub.com:4000/';
  socket = IO.io(
    serverUrl,
    IO.OptionBuilder()
        .setTransports(['websocket'])
        .disableAutoConnect()
        .build(),
  );

  socket?.connect();

  socket?.onConnect((_) {
    log('Connected to server with unique ID: $uniqueId');
    socket?.emit('sarthiId', uniqueId);
  });

  socket?.on('connectionResponse', (data) {
    log('Message from server: $data');
  });

  socket?.on('bookingUpdate', (data) async {
    log('Received bookingUpdate from server: $data');
    // I want to stream this data to the main app
  });

  socket?.onDisconnect((_) {
    log('Disconnected from server');
  });
}

@pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
  WidgetsFlutterBinding.ensureInitialized();
  DartPluginRegistrant.ensureInitialized();

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

  Timer.periodic(const Duration(seconds: 20), (timer) async {
    if (service is AndroidServiceInstance && await service.isForegroundService()) {
      log('Running background service');
      socket?.disconnect();
      connectWebSocket('uniqueId');
    }
  });

  await Firebase.initializeApp();
}
@pragma('vm:entry-point')
Future<bool> onBackground(ServiceInstance serviceInstance) async {
  WidgetsFlutterBinding.ensureInitialized();
  DartPluginRegistrant.ensureInitialized();
  await Firebase.initializeApp();
  return true;
}

我的问题:

如何将WebSocket数据(在后台服务中接收)以流的形式发送到主应用程序,以便它可以用于实时更新UI?

我尝试过的:

我知道 Flutter 中的 StreamController 和 Stream,但不确定如何使用后台服务中运行的 WebSocket 的数据来实现这一点。

即使应用程序位于后台,我也想保持此流连接,并在应用程序位于前台时更新 UI。

任何有关如何实现这一目标的帮助或建议将不胜感激!

flutter websocket background-service flutter-streambuilder flutter-background
1个回答
0
投票

基本示例

import 'dart:async';

import 'package:flutter/material.dart';

import 'package:flutter_background_service/flutter_background_service.dart';

Future<void> main() async {   WidgetsFlutterBinding.ensureInitialized();   await initializeService();   runApp(const MyApp()); }

Future<void> initializeService() async {   final service = FlutterBackgroundService();

  await service.configure(
    androidConfiguration: AndroidConfiguration(
      // this will be executed when app is in foreground or background in separated isolate
      onStart: onStart,

      // auto start service
      autoStart: false,
      isForegroundMode: false,
    ),
    iosConfiguration: IosConfiguration(
      // auto start service
      autoStart: false,

      // this will be executed when app is in foreground in separated isolate
      onForeground: onStart,
    ),   ); }

void onStart(ServiceInstance service) async {   service.on('toServer').listen((data) {
    ///////////////////////////////////////////////////
    //here you code use websocket to send data to server   });

  ////////////////////////////////////////////////////////   //here you code use websocket to receive data from server   await Future.delayed(const Duration(seconds: 1));   service.invoke('fromServer', {"data": "Text expample 1 secons"});   await Future.delayed(const Duration(seconds: 5));   service.invoke('fromServer', {"data": "Text expample 5 secons"}); }

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

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

class _MyAppState extends State<MyApp> {   final bgService = FlutterBackgroundService();

  @override   Widget build(BuildContext context) {
    final Stream<Map<String, dynamic>?> fromServer = bgService.on('fromServer');

    //Send data to server
    bgService.invoke('toServer', {"data": "Text expample"});

    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Material App Bar'),
        ),
        body: Center(
          child: StreamBuilder<Map<String, dynamic>?>(
            stream: fromServer,
            builder: (context, snapshot) {
              if (!snapshot.hasData) {
                return const CircularProgressIndicator();
              }
              return Text(
                snapshot.data!['data'].toString(),
                style: const TextStyle(fontSize: 24),
              ); 
            },
          ),
        ),
      ),
    );   } }
© www.soinside.com 2019 - 2024. All rights reserved.