微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Flutter FutureProvider值未在Builder方法中更新

如何解决Flutter FutureProvider值未在Builder方法中更新

问题

我正在Flutter中构建一个基本应用程序,该应用程序可以获取用户的位置并以类似于Tinder的刷卡格式显示附近的地点。我设法实现了地理位置,但是在使用FutureProvider / Consumer时遇到一个奇怪的错误,即用户到该地点的相对距离被卡片组中的第一个距离值覆盖。尽管我不熟悉Flutter和Provider程序包,但我相信对此有一个简单的解决方法

附带说明: 在Google上搜索之后,我尝试使用FutureProvider.value()来防止旧值更新,但没有运气。

在此先感谢您的帮助或指导!

快速演示

FutureProvider Bug Demo

使用的包裹

packages used

card_swipe.dart

Command Line Task

geolocator_service.dart

import 'package:Flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:provider/provider.dart';
import 'package:swipe_stack/swipe_stack.dart';

import '../services/geolocator_service.dart';
import '../models/place.dart';

class CardSwipe extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final _currentPosition = Provider.of<Position>(context);
    final _placesProvider = Provider.of<Future<List<Place>>>(context);
    final _geoService = GeoLocatorService();

    return FutureProvider(
      create: (context) => _placesProvider,child: Scaffold(
        backgroundColor: Colors.grey[300],body: (_currentPosition != null)
            ? Consumer<List<Place>>(
                builder: (_,places,__) {
                  return (places != null)
                      ? Column(
                          children: [
                            SizedBox(height: 10.0),Container(
                              margin: EdgeInsets.only(top: 120.0),height: 600,child: Swipestack(
                                children: places.map((place) {
                                  return SwiperItem(builder:
                                      (SwiperPosition position,double progress) {
                                    return FutureProvider(
                                      create: (context) =>
                                          _geoService.getdistance(
                                              _currentPosition.latitude,_currentPosition.longitude,place.geometry.location.lat,place.geometry.location.lng),child: Consumer<double>(
                                          builder: (_,distance,__) {
                                        return (distance != null)
                                            ? Center(
                                                child: Card(
                                                  child: Container(
                                                    height: 200,width: 200,child: Center(
                                                      child: Column(
                                                        mainAxisAlignment:
                                                            MainAxisAlignment
                                                                .center,children: [
                                                          Text(place.name),Text(
                                                              '${(distance / 1609).toStringAsFixed(3)} mi'),// convert meter to mi
                                                        ],),)
                                            : Container();
                                      }),);
                                  });
                                }).toList(),visibleCount: 3,stackFrom: StackFrom.Top,translationInterval: 6,scaleInterval: 0.03,onEnd: () => debugPrint("onEnd"),onSwipe: (int index,SwiperPosition position) =>
                                    debugPrint("onSwipe $index $position"),onRewind:
                                    (int index,SwiperPosition position) =>
                                        debugPrint("onRewind $index $position"),],)
                      : Center(
                          child: CircularProgressIndicator(),);
                },)
            : Center(
                child: CircularProgressIndicator(),);
  }
}

place.dart

快速说明: Place类确实导入了一个名为geometry.dart的自定义类,但这纯粹是为了构造Place对象,我确定它不会影响错误。因此,已将其省略。

import 'package:geolocator/geolocator.dart';

class GeoLocatorService {
  final geolocator = Geolocator();

  Future<Position> getLocation() async {
    return await geolocator.getCurrentPosition(
      desiredAccuracy: LocationAccuracy.high,locationPermissionLevel: GeolocationPermission.location,);
  }

  Future<double> getdistance(
      double startLat,double startLng,double endLat,double endLng) async {
    return await geolocator.distanceBetween(startLat,startLng,endLat,endLng);
  }
}

解决方法

您必须向SwiperItem添加一个具有唯一值(例如地点名称)的键,因为当前的颤抖认为该小部件保持不变,因此Consumer的状态为最旧的最上面的小部件。 通过添加键,您可以告诉flutter您删除了最上面的窗口小部件,而新的最上面的窗口小部件实际上是第二个窗口小部件

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。