Reputation: 65
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
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