【问题标题】:Flutter listview not updating after data update数据更新后颤振列表视图不更新
【发布时间】:2020-06-03 21:19:13
【问题描述】:

我在 bottomSheet 中有一个 ListView,它是使用元素数组构建的。目前我在那里有一个“空”项目,然后是.clear()ed,并在异步数据库调用后填充。

变量更新是正确的,我尝试使用setState((){}),但 ListView 根本没有更新。我需要关闭 bottomSheet,重新打开它,然后 ListView 就会有正确的项目。

我只需要致电setState 还是需要标记bottomSheet 构建器才能更新?

主 ListView 部分:

 @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('My Map'),
          backgroundColor: Colors.green[700],
        ),

        //Put in a stack widget so can layer other widgets on top of map widget
        body: Stack(
          children: <Widget>[
            GoogleMap(
              mapType: _currentMapType,
              markers: _markers,
              onMapCreated: _onMapCreated,
              onCameraMove: _onCameraMove,
              initialCameraPosition: CameraPosition(
                target: _center,
                zoom: 11.0,
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(16.0),
              child: Align(
                  alignment: Alignment.bottomCenter,
                  child: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                    SizedBox(width: 16.0),

                    Builder(
                      builder: (context) => FloatingActionButton(   
                          ...
                      ),

                    ),

                    SizedBox(width: 16.0),

                    FloatingActionButton(
                      ...
                    ),

                    SizedBox(width: 16.0),

                    Builder(
                      builder: (context) => FloatingActionButton(
                          child: Icon(Icons.file_download, size: 36.0),
                          backgroundColor: Colors.green,
                          onPressed: () {
                            showBottomSheet(
                                context: context,
                                builder: (context) {
                                  return ListView(
                                    padding: EdgeInsets.all(15.0),
                                    children: <Widget>[

                                         ...

                                      Divider(),

                                      ListTile(
                                        title: Text("Remote JSON Download"),
                                        trailing:
                                        Icon(Icons.refresh),
                                        selected: true,
                                        onTap: _OnPressedReloadJSON,               <-------------
                                      ),

                                      Divider(),

                                      Container(
                                        height: 150.0,
                                        child: ListView.builder(               <-------------
                                          scrollDirection: Axis.horizontal,

                                          itemCount : testList.length, 
                                          itemBuilder: (BuildContext context, int index) {
                                              return Container(
                                                padding: EdgeInsets.all(5.0),
                                                margin: EdgeInsets.all(5.0),
                                                width: 150.0,
                                                color: Colors.red,
                                                child: Text(testList[index]),
                                              );
                                          },

                                        ),
                                      ),

异步获取:

class _MyAppState extends State<MyApp> {

  ...

  _OnPressedReloadJSON() {
    fetchJSONAndMakeListTile();
  }

  ...

  List<String> testList= ["empty"];

  Future<http.Response> fetchJSONAndMakeListTile() async {
    final response = await http.get('https://..... file.json');

    // If the server did return a 200 OK response, then parse the JSON.
    if (response.statusCode == 200) {
      List<db_manager.MyObject> myObjects = (json.decode(response.body) as List)
          .map((e) => db_manager.MyObject.fromJson(e))
          .toList();

      testList.clear();
      myObjects.forEach((db_manager.MyObject al) {
        testList.add(al.code);
        print("debug:"+al.code+" - "+al.name);        <------------- prints correctly
      });

      //TODO Does this even work?
      //Trigger update of state - ie redraw/reload UI elements
      setState(() {});

    } else {
      // If the server did not return a 200 OK response, then throw an exception.
      print(response);
      throw Exception('Failed to load json');
    }
  }

更新:

我已将 BottomSheet 构建器抽象为另一个类(根据另一个答案)作为它自己的 StatefulWidget,但我似乎无法从我的主 dart 文件中访问 void onPress() 方法。如果 BottomSheet 创建/构建器在这个单独的 dart 文件中,我如何调用它来构建,然后使用 async 调用更新列表视图内容列表来更新其状态?

BottomSheetWidget.dart

class BottomSheetDatabases extends StatefulWidget {
  @override
  _BottomSheetDatabases createState() => _BottomSheetDatabases();
}

class _BottomSheetDatabases extends State<BottomSheetDatabases> {

  void _onpress() {

  }

  void loadMe() {

  }

  List<String> testList= ["empty"];

  @override
  Widget build(BuildContext context) {
    return BottomSheet(

        builder: (context) {
          return ListView(
            padding: EdgeInsets.all(15.0),
            children: <Widget>[
              ListTile(
                ...

              ),

              Divider(),

              Container(
                height: 150.0,
                child: ListView.builder(
                  scrollDirection: Axis.horizontal,

                  itemCount: testList.length,
                  itemBuilder: (BuildContext context, int index) {
                    return Container(
                      key: UniqueKey(),
                      //TODO  ??
                      padding: EdgeInsets.all(5.0),
                      margin: EdgeInsets.all(5.0),
                      width: 150.0,
                      color: Colors.red,
                      child: Text(testList[index]),
                    );
                  },

                ),
                //),
                //),
              ),

              ...

Main.dart

  void _loadSheetDatabases() {
    BottomSheetWidget bottomSheetwidget = BottomSheetWidget();
    bottomSheetwidget.loadMe();
  }

【问题讨论】:

    标签: android-studio listview flutter dart


    【解决方案1】:

    在我看来,ListView.Builder 返回的小部件中缺少 Key,请尝试将 UniqueKey() 或 ValueKey 放入容器或文本中:

    Container(
       key: UniqueKey(),
       padding: EdgeInsets.all(5.0),
       margin: EdgeInsets.all(5.0),
       width: 150.0,
       color: Colors.red,
       child: Text(testList[index]),
    );
    

    【讨论】:

    • 感谢它实际上对我有用。 UniqueKey 使它工作。唯一的区别是我没有使用 setState 而是将数据推送到流
    • 为我工作。没有它 setState 什么也没做。
    • setState 有时不适用于inheritedWidget。添加 UniqueKey() 成功了。谢谢;)
    • 这应该是公认的答案。像魅力一样工作。
    • 这个答案是救命稻草
    【解决方案2】:

    您的ListView 仅在您的FloatingActionButton 上调用onPressed 时构建。
    我认为这就是为什么当状态发生变化时它不会再次构建的原因。

    您可以包装代码以在具有自己状态的新 StatefulWidget 中构建 ListView,然后在 testList 更改时更新它。

    【讨论】:

    • 所以,第二个dart 文件,extends StatefulWidget,然后是 CreateState,新类扩展 State,然后有 Widget build(BC ctx) { return BottomSheet( builder: ....
    • 是的,应该可以!您可以添加一个名为 updateList(List&lt;String&gt; list) 的方法并持有对小部件的引用以更新它
    • 嗯,似乎无法正常工作。我已经更新了问题
    猜你喜欢
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    • 2021-06-28
    • 2020-04-19
    • 1970-01-01
    • 2018-09-10
    • 2017-11-11
    • 1970-01-01
    相关资源
    最近更新 更多