Jacob Pyke
Jacob Pyke

Reputation: 65

Flutter Retrieve Correct Value From Stream

I have been attempting to get a beacon Package to work within flutter. The url for the package is https://pub.dartlang.org/packages/flutter_beacon/.

However, the problem that i am having is when I beaconStream.listen(print); then I get this output to the console:

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": []}

As you can see, for whatever reason one beacon is duplicated.

However, when I connect my ScanBeacons function to a FutureBuilder widget, I only recieve this data from the stream:

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

My guess is that for some reason my function is executing twice, and FutureBuilder is reading the data from only the first stream that is being created, however just a thought, im not too sure. Any help is appreciated!

The way that I have done it probably isnt the most efficient, so any input on how to restructure the code would be appreciated!

EDIT: Of course I was getting a duplicate value, I was printing it twice 🤦🏼‍♂️ Anyways, Problem still persists, My streambuilder doesnt line up with the data from listen.

Code for the widget:

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()));
          }
        },
      ),
    );
  }
}
```

Upvotes: 3

Views: 4829

Answers (1)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657376

If scanBeacons() returns a new Future with every call, the beacons will be fetched every time the UI is rebuilt.
Instead move the code to initState() (or outside of widgets entirely) and invoke the call there and call setState() to have the UI rebuilt when data arrives.

Upvotes: 4

Related Questions