我正在运行一个搜索过滤功能,它从地板数据库中检索球员.功能运行良好,我可以通过日志(log)看到新的播放器被返回,但是我的用户界面不会更新,似乎是来self 分配的新列表,不会触发重新渲染.

有人能看到我的代码出了什么问题吗?

    import 'package:flutter/material.dart';

import '../database/LocalDatabase.dart';
import '../model/Player.dart';

class Pitch extends StatefulWidget {
  const Pitch({super.key});

  @override
  _Pitch createState() => _Pitch();
}

class _Pitch extends State<Pitch> {
  List<Player> playersList = <Player>[];

  Offset positionOne = const Offset(100, 100);
  Offset positionTwo = const Offset(200, 100);

  @override
  Widget build(BuildContext context) {
    return Container(
      constraints: BoxConstraints.expand(),
      color: Colors.white,
      child: Stack(
        alignment: Alignment.center,
        children: [
          Image.asset("assets/images/pitch.png"),
          Positioned(
            left: positionOne.dx,
            top: positionOne.dy,
            child: Draggable(
              feedback: playerImage(
                  "https://cdn.sofifa.net/players/158/023/22_120.png"),
              childWhenDragging: Opacity(
                opacity: 0,
                child: playerImage(
                    "https://cdn.sofifa.net/players/158/023/22_120.png"),
              ),
              child: playerImage(
                  "https://cdn.sofifa.net/players/158/023/22_120.png"),
              onDragEnd: (details) {
                setState(() {
                  positionOne = details.offset;
                });
              },
            ),
          ),
          Positioned(
            left: positionTwo.dx,
            top: positionTwo.dy,
            child: Draggable(
              feedback: playerImage(
                  "https://cdn.sofifa.com/players/notfound_0_120.png"),
              childWhenDragging: Opacity(
                opacity: 0,
                child: playerImage(
                    "https://cdn.sofifa.com/players/notfound_0_120.png"),
              ),
              child: playerImage(
                  "https://cdn.sofifa.com/players/notfound_0_120.png"),
              onDragEnd: (details) {
                setState(() {
                  positionTwo = details.offset;
                });
              },
            ),
          )
        ],
      ),
    );
  }

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

    // getPlayers().then((value) {
    //   debugPrint("playerfromdb: ${value[0].name}");
    // });
  }

  Future<List<Player>> getPlayers() async {
    final database =
        await $FloorLocalDatabase.databaseBuilder('local_database.db').build();

    final playerDao = database.playerDao;

    final players = playerDao.getAllPlayers();

    return players;
  }

  Widget playerImage(String imageUrl) {
    return GestureDetector(
        onTap: () => showDialog<void>(
            context: context,
            builder: (BuildContext context) => Dialog(
                backgroundColor: Colors.white,
                child: SizedBox(
                    height: 300,
                    width: 300,
                    child: Column(
                      children: [
                        const SizedBox(height: 24),
                        Container(
                            margin: const EdgeInsets.only(left: 16),
                            height: 48,
                            child: TextField(
                              decoration: const InputDecoration.collapsed(
                                  hintText: 'Enter player name',
                                  focusColor: Colors.transparent),
                              onChanged: (value) {
                                searchPlayers(value);
                              },
                            )),
                        const SizedBox(height: 24),
                        SizedBox(
                          height: 200,
                          child: ListView.builder(
                              itemCount: playersList.length,
                              itemBuilder: (context, index) {
                                return playerItem(playersList.elementAt(index));
                              }),
                        ),
                      ],
                    )))),
        child: SizedBox(
          width: 48,
          height: 48,
          child: Image.network(imageUrl),
        ));
  }

  Widget playerItem(Player? player) {
    return Container(
      height: 48,
      margin: const EdgeInsets.all(8),
      padding: const EdgeInsets.only(left: 8, right: 8),
      decoration: BoxDecoration(
          shape: BoxShape.rectangle,
          color: Colors.white,
          borderRadius: BorderRadius.circular(16),
          boxShadow: const [BoxShadow(blurRadius: 8)]),
      child: Row(
        children: [
          SizedBox(
              height: 36,
              width: 36,
              child: Image.network(player?.playerImageUrl ?? "")),
          const SizedBox(width: 8),
          Text(player?.name ?? "")
        ],
      ),
    );
  }

  Future<void> searchPlayers(String query) async {
    final database = await $FloorLocalDatabase
        .databaseBuilder('local_database.db')
        .build();

    final playerDao = database.playerDao;

    // await List<Player> filteredPlayers =
   playerDao.searchPlayers(query).then((value) {
      setState(() => playersList = value);
      debugPrint(value[0].name);
    });
  }
}

推荐答案

因为你在对话框中放了ListView.builder,所以它会创建一个新的堆栈,而一个新的堆栈不能从另一个堆栈重新渲染

您可以通过为对话框创建新的有状态小部件来更改代码

import 'package:flutter/material.dart';

import '../database/LocalDatabase.dart';
import '../model/Player.dart';

class Pitch extends StatefulWidget {
  const Pitch({super.key});

  @override
  _Pitch createState() => _Pitch();
}

class _Pitch extends State<Pitch> { 

  Offset positionOne = const Offset(100, 100);
  Offset positionTwo = const Offset(200, 100);

  @override
  Widget build(BuildContext context) {
    return Container(
      constraints: BoxConstraints.expand(),
      color: Colors.white,
      child: Stack(
        alignment: Alignment.center,
        children: [
          Image.asset("assets/images/pitch.png"),
          Positioned(
            left: positionOne.dx,
            top: positionOne.dy,
            child: Draggable(
              feedback: playerImage(
                  "https://cdn.sofifa.net/players/158/023/22_120.png"),
              childWhenDragging: Opacity(
                opacity: 0,
                child: playerImage(
                    "https://cdn.sofifa.net/players/158/023/22_120.png"),
              ),
              child: playerImage(
                  "https://cdn.sofifa.net/players/158/023/22_120.png"),
              onDragEnd: (details) {
                setState(() {
                  positionOne = details.offset;
                });
              },
            ),
          ),
          Positioned(
            left: positionTwo.dx,
            top: positionTwo.dy,
            child: Draggable(
              feedback: playerImage(
                  "https://cdn.sofifa.com/players/notfound_0_120.png"),
              childWhenDragging: Opacity(
                opacity: 0,
                child: playerImage(
                    "https://cdn.sofifa.com/players/notfound_0_120.png"),
              ),
              child: playerImage(
                  "https://cdn.sofifa.com/players/notfound_0_120.png"),
              onDragEnd: (details) {
                setState(() {
                  positionTwo = details.offset;
                });
              },
            ),
          )
        ],
      ),
    );
  }

  Widget playerImage(String imageUrl) {
    return GestureDetector(
      onTap: () => showDialog<void>(
        context: context,
        builder: (BuildContext context) => Dialog(
          backgroundColor: Colors.white,
          child: const PlayersDialog(),
        ),
      ),
      child: SizedBox(
        width: 48,
        height: 48,
        child: Image.network(imageUrl),
      ),
    );
  }
 


}


class PlayersDialog extends StatefulWidget {
  const PlayersDialog({super.key});

  @override
  _PlayersDialog createState() => _PlayersDialog();

}

class _PlayersDialog extends State<PlayersDialog> {
  List<Player> playersList = <Player>[];

  Future<void> searchPlayers(String query) async {
    final database =
        await $FloorLocalDatabase.databaseBuilder('local_database.db').build();

    final playerDao = database.playerDao;

    // await List<Player> filteredPlayers =
    playerDao.searchPlayers(query).then((value) {
      setState(() => playersList = value);
      debugPrint(value[0].name);
    });
  }
  @override
  Widget build(BuildContext context) {
    return SizedBox(
            height: 300,
            width: 300,
            child: Column(
              children: [
                const SizedBox(height: 24),
                Container(
                    margin: const EdgeInsets.only(left: 16),
                    height: 48,
                    child: TextField(
                      decoration: const InputDecoration.collapsed(
                          hintText: 'Enter player name',
                          focusColor: Colors.transparent),
                      onChanged: (value) {
                        searchPlayers(value);
                      },
                    )),
                const SizedBox(height: 24),
                SizedBox(
                  height: 200,
                  child: ListView.builder(
                    itemCount: playersList.length,
                    itemBuilder: (context, index) {
                      return playerItem(playersList.elementAt(index));
                    },
                  ),
                ),
              ],
            ),
          );
  }

    Widget playerItem(Player? player) {
    return Container(
      height: 48,
      margin: const EdgeInsets.all(8),
      padding: const EdgeInsets.only(left: 8, right: 8),
      decoration: BoxDecoration(
          shape: BoxShape.rectangle,
          color: Colors.white,
          borderRadius: BorderRadius.circular(16),
          boxShadow: const [BoxShadow(blurRadius: 8)]),
      child: Row(
        children: [
          SizedBox(
              height: 36,
              width: 36,
              child: Image.network(player?.playerImageUrl ?? "")),
          const SizedBox(width: 8),
          Text(player?.name ?? "")
        ],
      ),
    );
  }

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

    // getPlayers().then((value) {
    //   debugPrint("playerfromdb: ${value[0].name}");
    // });
  }

  Future<List<Player>> getPlayers() async {
    final database =
        await $FloorLocalDatabase.databaseBuilder('local_database.db').build();

    final playerDao = database.playerDao;

    final players = playerDao.getAllPlayers();

    return players;
  }

}
  

Flutter相关问答推荐

无法在Flatter中设计正确的布局

在Flutter中,CachedNetworks Image不工作(不从CachedData加载)

Android元数据为1.9.0,预期版本为1.7.1,如何解决flutter应用程序构建失败问题?

为什么要在值列表中两次放入空安全性

在Flutter 中实现中小型应用程序栏标题

摆动如何更改弹出菜单项高亮显示 colored颜色 半径

如何使排内 children 的身高与其他排内 children 的身高相适应?

使用持久的侧边菜单和顶部栏在Ffltter Web应用程序中的页面之间导航

使索引[0]在ListViewBuilder中返回字符串1

未处理的异常:第1行第5列出现错误:无效的媒体类型:应为/&;.从API获取数据时在Flutter中

Flutter 附近的连接

运行任何 flutter 命令都会显示无法安装 <版本>

如何更改 DropDownMenu 的显示方向?

Flutter 动画页面计数器文本

如何在 flutter 的 onChanged(更改字符)处更改 TextField 边框 colored颜色 ?

Flutter 中父容器顶部的 Gridview 间距额外区域

在 flutter 中使用 StreamBuilder 在文本字段中键入时显示过滤记录

如何按键在 map 列表中搜索

如何在Flutter 中制作自定义微调器?

用于空值 FirebaseFirestore 的空值判断运算符