Flutter从流中检索正确的值

时间:2019-03-05 14:20:44

标签: dart flutter

我一直在尝试获取一个信标程序包,以使其在抖动中正常工作。软件包的网址为https://pub.dartlang.org/packages/flutter_beacon/

但是,我遇到的问题是当我beaconStream.listen(print);然后将此输出发送到控制台时:

flutter: RangingResult{"region": {"identifier":"Test","proximityUUID":"705DAEE5-56BC-415A-839B-4AE00FC29946","major":1,"minor":1}, "beacons": []}
flutter: RangingResult{"region": {"identifier":"T-Shirt Beacon","proximityUUID":"AFC0FF69-3ACB-4A99-9F6A-2A4B6F786619","major":1,"minor":1}, "beacons": []}
flutter: RangingResult{"region": {"identifier":"T-Shirt Beacon","proximityUUID":"AFC0FF69-3ACB-4A99-9F6A-2A4B6F786619","major":1,"minor":1}, "beacons": []}

如您所见,无论出于何种原因,一个信标都是重复的。

但是,当我将ScanBeacons函数连接到FutureBuilder小部件时,我仅从流中接收以下数据:

flutter: RangingResult{"region": {"identifier":"T-Shirt Beacon","proximityUUID":"AFC0FF69-3ACB-4A99-9F6A-2A4B6F786619","major":1,"minor":1}, "beacons": []}

我的猜测是,由于某种原因,我的函数执行了两次,并且FutureBuilder仅从正在创建的第一个流中读取数据,但是只是一个想法,我不太确定。任何帮助表示赞赏!

我完成此操作的方式可能不是最有效的,因此,感谢您提供任何有关重组代码的信息!

编辑: 当然我得到了重复的值,我将其打印了两次twice️ 无论如何,问题仍然存在,我的streambuilder不能与来自监听的数据保持一致。

窗口小部件的代码:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_beacon/flutter_beacon.dart';

class BeaconFetcher extends StatefulWidget {

  BeaconFetcher({Key key}) : super(key: key);

  _BeaconFetcherState createState() => _BeaconFetcherState();
}

class _BeaconFetcherState extends State<BeaconFetcher> {

  Future<List<Region>> fetchBeacons() async {
    List<Region> regions = [];
    regions = [
      Region(
          proximityUUID: 'AFC0FF69-3ACB-4A99-9F6A-2A4B6F786619',
          identifier: 'T-Shirt Beacon',
          major: 1,
          minor: 1),
      Region(
          proximityUUID: '705DAEE5-56BC-415A-839B-4AE00FC29946',
          identifier: 'Test',
          major: 1,
          minor: 1),
    ];
    return regions;
  }

  Future<Stream<RangingResult>> scanBeacons() async {
    await flutterBeacon.initializeScanning;
    List<Region> regions = await fetchBeacons();
    Stream<RangingResult> beaconStream = flutterBeacon.ranging(regions);
    beaconStream.listen(print); 
    return beaconStream;
  }

  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    double width = MediaQuery.of(context).size.width;
    return Container(
      // Future Builder for Fetching the stream that will be created
      child: FutureBuilder<Stream<RangingResult>>(
        future: scanBeacons(), //Function for fetching the stream
        builder: (BuildContext context,
            AsyncSnapshot<Stream<RangingResult>> snapshot) {
          //If the widget has managed to fetch the data
          if (snapshot.connectionState == ConnectionState.done) {
            //If the data isnt null
            if (snapshot.data != null) {
              //Create a new stream builder for listening to the data coming from the function
              return StreamBuilder<RangingResult>(
                  stream: snapshot.data,
                  builder: (BuildContext context,
                      AsyncSnapshot<RangingResult> streamSnapshot) {
                    if (streamSnapshot.data != null) {
                      print(streamSnapshot.data);
                      return Container(
                        child: Column(
                          children: <Widget>[
                            Text(
                              "List of Detected Beacons",
                              style: Theme.of(context).textTheme.headline,
                            ),
                            Container(
                              height: height,
                              width: width,
                              child: ListView.builder(
                                itemCount: streamSnapshot.data.beacons.length,
                                itemBuilder: (BuildContext context, int index) {
                                  return Column(
                                    children: <Widget>[
                                      Text(streamSnapshot
                                          .data.beacons[index].proximityUUID),
                                      Row(
                                        mainAxisAlignment:
                                            MainAxisAlignment.center,
                                        children: <Widget>[
                                          Text(
                                              "Major Value: ${streamSnapshot.data.beacons[index].major.toString()}"),
                                          Padding(
                                            padding:
                                                const EdgeInsets.only(left: 8),
                                            child: Text(
                                                "Minor Value: ${streamSnapshot.data.beacons[index].minor.toString()}"),
                                          ),
                                        ],
                                      ),
                                      Text(streamSnapshot
                                          .data.beacons[index].proximity
                                          .toString()),
                                    ],
                                  );
                                },
                              ),
                            ),
                          ],
                        ),
                      );
                    }
                  });
            } else {
              return Center(
                  child: Container(child: CircularProgressIndicator()));
            }
          } else {
            return Center(child: Container(child: CircularProgressIndicator()));
          }
        },
      ),
    );
  }
}
```

1 个答案:

答案 0 :(得分:0)

如果scanBeacons()每次调用都返回一个新的Future,则每次重建UI时都将获取信标。
而是将代码移动到initState()(或完全在窗口小部件外部)并在那里调用,然后调用setState()以便在数据到达时重建UI。