提供者从 ChangeNotifier 通知其他侦听器

时间:2021-07-22 23:41:46

标签: flutter flutter-provider

我有以下设置:

具有多个页面的应用:VoltagesPage & TemperaturesPage

我将通过蓝牙串行接收一些数据,如下所示:

bluetooth_data_provider.dart

import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter/widgets.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';

class BluetoothDataProvider with ChangeNotifier {
  String _data = '';
  String get data => _data;
  String _messageBuffer = '';

  BluetoothConnection? _connection;

  connectAndListen(String address) {
    BluetoothConnection.toAddress(address).then((connection) {
      print('Connected to the device');
      _connection = connection;

      if (_connection == null) {
        return;
      }

      _connection!.input!.listen(_onDataReceived).onDone(() {});
    }).catchError((error) {
      print('Cannot connect, exception occured');
      print(error);
    });
  }

  void _onDataReceived(Uint8List data) {
    String dataStr = ascii.decode(data);
    _messageBuffer += dataStr;

    if (dataStr.contains('\n')) {
      print(_messageBuffer);
      _data = _messageBuffer.substring(0, _messageBuffer.length - 1);
      _messageBuffer = '';

      notifyListeners();
    }
  }
}

这将通知所有监听 BluetoothDataProvider 对其 data 字段的更改的监听器。

现在 TemperaturesPage 对消息并不真正感兴趣,它是针对 VoltagesPage 的,反之亦然。我可以通过设备发送的前缀来确定谁应该接收消息。

电压消息可能如下所示:

V:+12.5

温度消息可能如下所示:

T:+45.6

现在,当我从两个页面观看 BluetoothDataProvider 时,小部件必须决定是否接受消息。但这可能会使小部件挂起,因为它仍然需要在调用 build 时重建小部件。

我真正想要的是这样的:

import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter/widgets.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';

class BluetoothDataProvider with ChangeNotifier {
  String _data = '';
  String get data => _data;
  String _messageBuffer = '';

  BluetoothConnection? _connection;

  connectAndListen(String address) {
    BluetoothConnection.toAddress(address).then((connection) {
      print('Connected to the device');
      _connection = connection;

      if (_connection == null) {
        return;
      }

      _connection!.input!.listen(_onDataReceived).onDone(() {});
    }).catchError((error) {
      print('Cannot connect, exception occured');
      print(error);
    });
  }

  void _onDataReceived(Uint8List data) {
    String dataStr = ascii.decode(data);
    _messageBuffer += dataStr;

    if (dataStr.contains('\n')) {
      print(_messageBuffer);
      _data = _messageBuffer.substring(0, _messageBuffer.length - 1);
      _messageBuffer = ''; 

      if(_data.startsWith("T:")) {
        // notify with a TemperatureProvider
      } else if (_data.startsWith("V:")){
        // notify with a VoltageProvider
      }
    }
  }
}

这样,每个页面都可以监听不同的 Provider,并且只接收他们真正感兴趣的数据。

这样的场景有可能吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

我现在解决了这个问题。

在我的 main.dart 中,我将只在 BluetoothDataProvider 中创建一个 initState() 实例,并将从那里获取的上下文提供给 BluetoothDataProvider 的构造函数。

之后,我可以随意使用上下文调用不同的提供者,如下所示:

void _onDataReceived(Uint8List data) {
  String dataStr = ascii.decode(data);
  _messageBuffer += dataStr;
  if (dataStr.contains('\n')) {
    print(_messageBuffer); // here you get complete string
    _data = _messageBuffer.substring(0, _messageBuffer.length - 1);
    _messageBuffer = ''; //clear buffer to accept new string
    var messageType = _data.substring(0, 2);

    switch (messageType) {
      case "V:":
        context.read<CurrentReceivedMessage>().setMessage(_data);
        break;
      case "T:":
        context.read<TemperatureReceivedMessage>().setMessage(_data);
        break;
    }
  }
}