Flutter 使用颤振提供程序将数据传递到另一个屏幕

Flutter 使用颤振提供程序将数据传递到另一个屏幕,flutter,mobile,flutter-dependencies,flutter-provider,Flutter,Mobile,Flutter Dependencies,Flutter Provider,我试图使用提供程序将数据传递到另一个屏幕,但似乎我总是传递相同的数据,除非我对列表进行排序,然后传递不同的数据(这意味着我可能通过对列表进行排序来切换索引,这就是它现在传递不同数据的原因)。简言之,我调用API,填充列表,为下一页设置提供程序,然后单击“列出上一屏幕中的信息”,但问题是除非对列表进行排序,否则我总是显示相同的项目。代码如下: 调用API并显示列表: var posts = <RideData>[]; var streamController = StreamCo

我试图使用
提供程序
将数据传递到另一个屏幕,但似乎我总是传递相同的数据,除非我对列表进行排序,然后传递不同的数据(这意味着我可能通过对列表进行排序来切换索引,这就是它现在传递不同数据的原因)。简言之,我调用API,填充列表,为下一页设置提供程序,然后单击“列出上一屏幕中的信息”,但问题是除非对列表进行排序,否则我总是显示相同的项目。代码如下:

调用API并显示列表:

 var posts = <RideData>[];
  var streamController = StreamController<List<RideData>>();

  @override
  void initState() {
    _getRideStreamList();
    super.initState();
  }

  _getRideStreamList() async {
    await Future.delayed(Duration(seconds: 3));
    var _vehicleStreamData = await APICalls.instance.getRides();

    var provider = Provider.of<RideStore>(context, listen: false);

    posts = await _vehicleStreamData
        .map<RideData>((e) => RideData.fromJson(e))
        .toList();

    streamController.add(posts);
    provider.setRideList(posts, notify: false);
  }

  bool isSwitched = true;
  void toggleSwitch(bool value) {
    if (isSwitched == false) {
      posts.sort((k1, k2) => k1.rideId.compareTo(k2.rideId));
    } else {
      posts.sort((k1, k2) => k2.rideId.compareTo(k1.rideId));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SafeArea(
        child: SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: Column(
            children: [
              TextButton(
                  child: Text('sort ascending'),
                  onPressed: () {
                    setState(() {
                      toggleSwitch(isSwitched = !isSwitched);
                    });
                  }),
              Container(
                height: 1000,
                child: StreamBuilder<List<RideData>>(
                    initialData: posts,
                    stream: streamController.stream,
                    builder: (context, snapshot) {
                      return ListView.builder(
                        shrinkWrap: true,
                        itemCount: snapshot.data.length,
                        itemBuilder: (context, index) {
                          return Column(
                            children: [
                              Row(
                                children: [
                                  Padding(
                                    padding: const EdgeInsets.only(left: 15.0),
                                    child: Text(
                                      'Ride #${snapshot.data[index].rideId}',
                                    ),
                                  ),
                                  FlatButton(
                                    textColor: Colors.blue[700],
                                    minWidth: 0,
                                    child: Text('View'),
                                    onPressed: () {
// here is where I pass the data to the RideInfo screen
                                      Navigator.push(
                                          context,
                                          MaterialPageRoute(
                                              builder: (context) => RideInfo(
                                                    rideId: snapshot
                                                        .data[index].rideId,
                                                  )));
                                    },
                                  ),
                                ],
                              ),
                              Column(
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                children: [
                                  Text(
                                    '${snapshot.data[index].pickupTime}',
                                  ),
                                  Text(
                                    '${snapshot.data[index].jobArrived}',
                                  ),
                                ],
                              ),
                            ],
                          );
                        },
                      );
                    }),
              ),
            ],
          ),
        ),
      ),
    );
  }


如何根据我在“行驶信息”屏幕中按下并传递的列表中的ID显示正确的信息,使其不会始终返回相同的数据?提前感谢您的帮助

有问题的代码位于
RideInfo

  ListView.builder(
      shrinkWrap: true,
      itemCount: 1,
      itemBuilder: (context, index) {
        RideData rides = rideStore.getRideByIndex(index);
索引始终是
1
,因此您总是显示第一个
RideData
。有多种选项可以修复它,例如将
索引
,甚至将
RideData
传递给
RideInfo
构造函数:

class RideInfo extends StatefulWidget {
  static const String id = 'ride_info_screen';
  String rideId;
  final int index;
  RideInfo({@required this.rideId, @required this.index, Key key})
      : super(key: key) {
以及:

我对代码有一些补充意见。首先,
ListView
RideInfo
中没有任何作用,所以将其删除

其次,不需要构造
streamController
,也不需要在父窗体中使用
StreamBuilder
。您的列表可在骑乘用品商店中找到。因此,您的父窗体可以有:

  Widget build(BuildContext context) {
    var data = Provider.of<RideStore>(context).rideList;
    ...
          Container(
            height: 1000,
            child:
                // StreamBuilder<List<RideData>>(
                //     initialData: posts,
                //     stream: streamController.stream,
                //     builder: (context, snapshot) {
                //       return
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: data.length,
initState
中删除对
\u getRideStreamList
的调用,并在调用
\u getRideStreamList
FutureBuilder
中包装
列表视图

          Container(
            height: 1000,
            child: FutureBuilder(
              future: _getRideStreamList(),
              builder: (ctx, snapshot) {
                if (!snapshot.hasData) {
                  return Center(child: CircularProgressIndicator());
                } else {
                  var data = snapshot.data;
                  return ListView.builder(
                    ...
                  );
                }
              },
            ),
          ),
这将在等待数据时显示循环压缩机指示器


请注意,这是一个快速破解-您不希望每次小部件重建时都读取数据。因此,
\u getRideStreamList
可以检查数据是否已被读取,并返回数据,而不是重新读取。

首先,我要感谢您提供的详细答案,非常感谢!我通过了
索引
在这种情况下,我不确定如何成功地将完整的
骑乘数据
传递到
骑乘信息
。其次,我使用了
流生成器
,没有
提供者
,所以在发布之前我没有机会重构它,但再次感谢您的提醒,我真的非常感谢。干杯别担心。您可以将
RideData
传递给构造函数上的
RideInfo
,就像任何值一样:
RideData ride;RideInfo({@required RideData this.ride})
根据您的建议,我删除了不必要的代码,现在的问题是我需要刷新我的小部件,因为
ListView.builder
在从API访问数据之前呈现小部件,我尝试使用
FutureBuilder
并使用了“Provider”,因为我正在调用API,但我也遇到了同样的问题…请参见我对
FutureBuilder
        RideData rides = rideStore.getRideByIndex(widget.index);
  Widget build(BuildContext context) {
    var data = Provider.of<RideStore>(context).rideList;
    ...
          Container(
            height: 1000,
            child:
                // StreamBuilder<List<RideData>>(
                //     initialData: posts,
                //     stream: streamController.stream,
                //     builder: (context, snapshot) {
                //       return
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: data.length,
  _getRideStreamList() async {
    ...
    return posts;
  }
          Container(
            height: 1000,
            child: FutureBuilder(
              future: _getRideStreamList(),
              builder: (ctx, snapshot) {
                if (!snapshot.hasData) {
                  return Center(child: CircularProgressIndicator());
                } else {
                  var data = snapshot.data;
                  return ListView.builder(
                    ...
                  );
                }
              },
            ),
          ),