es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Reconectar el flujo gRPC en Flutter.

Estoy creando una aplicación Flutter que utiliza gRPC para comunicarse con el servidor. Hasta ahora esto funciona bien, pero ahora quiero añadir funcionalidad de streaming. Logro hacer funcionar un stream, pero cuando la aplicación pasa al segundo plano y luego se vuelve a abrir, el stream no se reconecta automáticamente. ¿Cuál es la forma correcta de manejar esto?

Esta es mi implementación actual, con streaming bidireccional:

El método builder de un widget

@override
Widget build(BuildContext context) {
  final service = MyStreamService();

  return Scaffold(
    body: StreamBuilder<streamresponse>(
      stream: service.stateStream(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Text(snapshot.data!.timestamp.nanos.toString());
        }

        return const SizedBox();
      },
    ),
  );
}

La clase de servicio que maneja la conexión gRPC con el servidor. El servidor devuelve inmediatamente los datos de la solicitud como respuesta.

“`dart
class StreamService {
final StreamController<streamrequest> _controller;

StreamService() :
_controller = StreamController<streamrequest>();

void sendToStream() {
_controller.add(StreamRequest(
timestamp: Timestamp.fromDateTime(DateTime.now()),
));
}

Stream<streamresponse> stateStream() async* {
Stream<streamresponse> strm = StreamClient(
channel,
options: CallOptions(),
).stream(_controller.stream);
startStream();

<pre><code>await for (var event in strm) {
yield event;

// Enviar solicitud al servidor después de 1 segundo
Future.delayed(const Duration(seconds: 1), sendToStream);
}
</code></pre>

}
}
“`

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para manejar la reconexión automática del flujo cuando la aplicación Flutter pasa a segundo plano y luego se abre de nuevo, puedes escuchar los eventos del ciclo de vida de la aplicación y volver a conectar el flujo en el método initState del widget.

    Aquí tienes un ejemplo de implementación:

    El método builder de un widget

      @override
      Widget build(BuildContext context) {
        final service = MyStreamService();
    
        return Scaffold(
          body: StreamBuilder<streamresponse>(
            stream: service.stateStream(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data!.timestamp.nanos.toString());
              }
    
              return const SizedBox();
            },
          ),
        );
      }
    

    El servicio que maneja la conexión gRPC con el servidor. El servidor devuelve inmediatamente los datos de la solicitud como respuesta

    class StreamService {
      StreamController<streamrequest> _controller;
      StreamSubscription<applifecyclestate>? _lifecycleSubscription;
    
      StreamService() {
        _controller = StreamController<streamrequest>();
        _lifecycleSubscription = WidgetsBinding.instance?.addObserver(AppLifecycleObserver(
          onResume: () async {
            await startStream();
          },
        ));
      }
    
      Future<void> startStream() async {
        Stream<streamresponse> strm = StreamClient(
          _channel,
          options: CallOptions(),
        ).stream(_controller.stream);
    
        await for (var event in strm) {
          yield event;
    
          // Enviar solicitud al servidor después de 1 segundo
          Future.delayed(const Duration(seconds: 1), sendToStream);
        }
      }
    
      void sendToStream() {
        _controller.add(StreamRequest(
          timestamp: Timestamp.fromDateTime(DateTime.now()),
        ));
      }
    
      Stream<streamresponse> stateStream() {
        return startStream();
      }
    
      @override
      void dispose() {
        _controller.close();
        _lifecycleSubscription?.cancel();
      }
    }
    

    En esta implementación, agregamos un AppLifecycleObserver en el constructor del servicio para escuchar el evento onResume. Cuando ocurre este evento, llamamos a startStream() para reconectar el flujo. También modificamos el método startStream() para que devuelva un Future<void> en lugar de un Stream<streamresponse>. Al hacer esto, podemos llamar a startStream() en el método initState del widget y esperar a que se complete antes de devolver el widget. Esto asegura que el flujo esté conectado antes de que se construya el widget. Por último, añadimos un método dispose() al servicio para cerrar el controlador del flujo y cancelar la suscripción al ciclo de vida de la aplicación cuando se desecha el widget.

Comments are closed.