如何从 flutter_reactive_ble 示例中获取 deviceServices

问题描述

我正在使用 Flutter_reactive_ble 项目 (https://github.com/PhilipsHue/flutter_reactive_ble) 中提供的示例,特别是在 device_detail_screen.dart 文件中。

它的工作原理和我认为的一样,但我想知道如何将 discoverServices(device.id) 的结果保存为变量,以便我可以显示它在文本小部件或其他东西中(至少这是计划)。每次尝试执行此操作时,都会收到一条错误消息:此表达式的类型为“void”,因此无法使用其值。

我相信这是因为它是 Future> 类型(见下面的声明)

Future> discoverServices (String deviceid)

我对此很陌生,所以我只是想弄清楚这一切是如何运作的。

每当我点击“发现服务”按钮时,所有服务都会出现在我的电脑终端中,但我希望它们最终出现在设备上。

如果您不想查看整个项目,这里是实际代码。我很确定这是适用的文件。我在查询的行上加上了“***”。

如果您需要更多信息或说明,请告诉我。谢谢!

import 'package:Flutter/material.dart';
import 'package:Flutter_reactive_ble/Flutter_reactive_ble.dart';
import 'package:Flutter_reactive_ble_example/src/ble/ble_device_connector.dart';
import 'package:provider/provider.dart';

class DeviceDetailScreen extends StatelessWidget {
  final discoveredDevice device;

  const DeviceDetailScreen({@required this.device}) : assert(device != null);

  @override
  Widget build(BuildContext context) =>
      Consumer2<BleDeviceConnector,ConnectionStateUpdate>(
        builder: (_,deviceConnector,connectionStateUpdate,__) =>
            _DeviceDetail(
          device: device,connectionUpdate: connectionStateUpdate != null &&
                  connectionStateUpdate.deviceid == device.id
              ? connectionStateUpdate
              : ConnectionStateUpdate(
                  deviceid: device.id,connectionState: DeviceConnectionState.disconnected,failure: null,),connect: deviceConnector.connect,disconnect: deviceConnector.disconnect,discoverServices: deviceConnector.discoverServices,);
}

class _DeviceDetail extends StatelessWidget {
  const _DeviceDetail({
    @required this.device,@required this.connectionUpdate,@required this.connect,@required this.disconnect,@required this.discoverServices,Key key,})  : assert(device != null),assert(connectionUpdate != null),assert(connect != null),assert(disconnect != null),assert(discoverServices != null),super(key: key);

  final discoveredDevice device;
  final ConnectionStateUpdate connectionUpdate;
  final void Function(String deviceid) connect;
  final void Function(String deviceid) disconnect;
  final void Function(String deviceid) discoverServices;

  bool _deviceConnected() =>
      connectionUpdate.connectionState == DeviceConnectionState.connected;

  @override
  Widget build(BuildContext context) => WillPopScope(
        onWillPop: () async {
          disconnect(device.id);
          return true;
        },child: Scaffold(
          appBar: AppBar(
            title: Text(device.name ?? "unkNown"),body: Center(
            child: SafeArea(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,crossAxisAlignment: CrossAxisAlignment.center,children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.all(8.0),child: Text(
                      "ID: ${connectionUpdate.deviceid}",style: const TextStyle(fontWeight: FontWeight.bold),Padding(
                    padding: const EdgeInsets.all(8.0),child: Text(
                      "Status: ${connectionUpdate.connectionState}",Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: <Widget>[
                      Padding(
                        padding: const EdgeInsets.all(8.0),child: ElevatedButton(
                          onpressed: !_deviceConnected()
                              ? () => connect(device.id)
                              : null,child: const Text("Connect"),Padding(
                        padding: const EdgeInsets.all(8.0),child: ElevatedButton(
                          onpressed: _deviceConnected()
                              ? () => disconnect(device.id)
                              : null,child: const Text("disconnect"),],Row(
                    mainAxisAlignment: MainAxisAlignment.center,children: [
                      Padding(
                        padding: const EdgeInsets.all(8.0),child: ElevatedButton(
                          // onpressed: _deviceConnected()                    // *** original code from example
                          //     ? () => discoverServices(device.id)          // *** original code from example
                          //     : null,// *** original code from example
                          onpressed: (){
                            if (_deviceConnected()){                          // *** My attempt at storing as a variable (this entire anonymous function)
                              var services = discoverServices(device.id);
                              print("services: $services");                   // *** services is underlined with an error: This expression has a type of 'void' so its value can't be used.
                            }
                          },child: const Text("discover Services"),Text("data"),// *** Where I'd like to populate the results of the discoverServices(device.id)
                ],);
}

解决方法

我期望您的 BleDeviceConnector 等于 this

如果您想使用 FlutterReactiveBle::discoverServices(...) 中的值 List<DiscoveredService>,您必须将您的 BleDeviceConnector::discoverServices(...) 函数修改为...

Future<List<DiscoveredService>> discoverServices(String deviceId) => _ble.discoverServices(deviceId);

你的 onPressed 回调到...

onPressed: () async {
    if (_deviceConnected()) {
        var services = await discoverServices(device.id);
        print("services: $services");
        // TODO: Insert your code to update the UI of "Text("data"),"
    }
},

编辑: 您还需要将 _DeviceDetaildiscoverServices 修改为...

final Future<List<DiscoveredService>> Function(String deviceId) discoverServices;