简体   繁体   中英

Flutter - FutureBuilder works well on Android but not well on iOS

I implemented the FutureBuilder with the code below in order to get the distance from the user and the item that he wants buy but I get a weird result between Android and iOS .

On Android works well and I get the distance for each item. But on iOS I don't have the distance for each item and infact some item has the distance and some items get null value.

在此处输入图像描述

class ProductHorizontalListItem extends StatelessWidget {
  const ProductHorizontalListItem({
    Key? key,
    required this.product,
    required this.coreTagKey,
    this.onTap,
  }) : super(key: key);

  final Product product;
  final Function? onTap;
  final String coreTagKey;

  @override
  Widget build(BuildContext context) {
    final PsValueHolder valueHolder =
    Provider.of<PsValueHolder>(context, listen: false);

    Future<double> getCurrentLocation() async {
          Position position = await Geolocator.getCurrentPosition();
          double lat = position.latitude;
          double long = position.longitude;
          final double distanceInMeters = Geolocator.distanceBetween(
            double.parse(position.latitude.toString()),
            double.parse(position.longitude.toString()),
            double.parse(product.itemLocation!.lat.toString()),
            double.parse(product.itemLocation!.lng.toString()),
          );

            return Future.value(distanceInMeters);

        }

        return FutureBuilder<double>(
                future: getCurrentLocation(),
            builder: (BuildContext context, AsyncSnapshot<double> snapshot) {
        return InkWell(
        onTap: onTap as void Function()?,
        child: Container(
            margin: const EdgeInsets.only(
                left: PsDimens.space4, right: PsDimens.space4,
                bottom: PsDimens.space12),
            child: Text(
                '${snapshot.data}',
                textAlign: TextAlign.start,
                style: Theme.of(context).textTheme.caption!.copyWith(
                    color: PsColors.textColor3
                )))

        );});
  }
}

I also tried to handle the states of FutureBuilder in each way but nothing.

iOS works bad, why?

I'm on Flutter 3.0.5 with Android Studio Chipmunk.

First, you should check the snapshot state before accessing its data. Otherwise you can get a null value, since the treatment has not been finished yet. Check snapshot.connectionState and snapshot.hasData before accessing snapshot.data .

Then, there is no need to convert latitudes and longitudes to String, then back to double.

Eventually, you can replace the definition of final Function? onTap; final Function? onTap; by a VoidCallback , to avoid parsing it in the Inkwell button.

Try this out:

@override
Widget build(BuildContext context) {
  Future<double> getCurrentLocation() async {
    Position position = await Geolocator.getCurrentPosition();
    final double distanceInMeters = Geolocator.distanceBetween(
      position.latitude,
      position.longitude,
      product.itemLocation!.latitude,
      product.itemLocation!.longitude,
    );
    return Future.value(distanceInMeters);
  }

  return FutureBuilder<double>(
    future: getCurrentLocation(),
    builder: (BuildContext context, AsyncSnapshot<double> snapshot) {
      if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
        return InkWell(
          onTap: onTap,
          child: Container(
            margin: const EdgeInsets.only(
              left: PsDimens.space4,
              right: PsDimens.space4,
              bottom: PsDimens.space12,
            ),
            child: Text(
              '${snapshot.data}',
              textAlign: TextAlign.start,
              style: Theme.of(context).textTheme.caption!.copyWith(
                    color: PsColors.textColor3,
                  ),
            ),
          ),
        );
      } else if (!snapshot.hasData) {
        // Handle error case
        return const Text('error');
      } else {
        // Display a loader or whatever to wait for the Future to complete
        return const Center(child: CircularProgressIndicator());
      }
    },
  );
}

I tried the code by replacing position and product.itemLocation by location of actual cities, and the distanceInMeters is correct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM