dart - 监听 StreamingController 并更新列表

标签 dart flutter

我想在进行流式传输时根据用户在搜索小部件中键入的内容不断更新播放器列表中的值。我知道我不能在播放器的 where 之后添加 add 但我只想让你知道我真正想做什么。这是我的代码:

load(StreamController controller) async {
var client = http.Client();
var req = http.Request('get', Uri.parse(PRO_PLAYERS_URL_API));
var streamRes = await client.send(req);

streamRes.stream
    .transform(utf8.decoder)
    .transform(json.decoder)
    .expand((e) => e)
    .map((map) => ProPlayer.fromJson(map))
    .pipe(streamController);
}

@override
void initState() {
// TODO: implement initState
super.initState();
streamController = StreamController.broadcast();
streamController.stream
    .listen((player) => setState(() => players.isEmpty ? players.add(player) : players.where((p) => p.alias.startsWith(_searchController.text)).toList().add((player))));

    load(streamController);
}

@override
Widget build(Buildcontext context) {
   return Container(
     padding: const EdgeInsets.symmetric(
       horizontal: 6.0,
       vertical: 4.0,
     ),
      child: Column(
       children: <Widget>[
         Padding(
           padding:
              const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
           child: TextField(
             controller: _searchController,
             decoration: InputDecoration(
                contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
               hintText: 'Search for player...',
               prefixIcon: Icon(Icons.search),
               suffixIcon: IconButton(
                onPressed: () {
                  setState(() {
                    _searchController.clear();
                 });
                },
                icon: Icon(Icons.close),
              ),
              border: OutlineInputBorder(
                 borderRadius: BorderRadius.circular(30.0)),
            ),
          ),
         ), Expanded(
              child: GridView.builder(
                shrinkWrap: true,
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                  childAspectRatio: 0.6,
                ),
                itemCount: players.length,
                itemBuilder: (_, int index) =>
                        ProPlayerItem(
                            player: players[index],
                            goToDetail: () => {},
                            goToSteam: () => _launchURL(
                                  players[index].profileUrl,
                                ),
                          ),
              ),
            ),
    ]
   )
  ) 
 }

更新:我希望在流式传输时输入搜索小部件时 gridview 不断更新,这可能吗?我尝试了上面的代码,但没有任何反应。

最佳答案

为什么您的方法不起作用

基本上,您正在尝试将两个独立的功能合并到一个列表中: 一方面,您希望从网络 API 加载所有播放器,另一方面,您希望根据某些条件过滤它们。

怎么办

我的谦虚建议是将 players 分成两个列表:一个用于所有玩家,另一个用于过滤后的玩家(那些实际应该显示的玩家)。

这样做的好处是两种功能可以彼此独立工作:如果用户在所有播放器加载后更改搜索查询,仍然可以通过过滤原始列表来显示有用的结果。

class _SearchWidgetState extends State<SearchWidget> {
  final _searchController = TextEditingController();
  final allPlayers = <ProPlayer>[];
  List<ProPlayer> filteredPlayers = <ProPlayer>[];

  load(StreamController controller) async { ... }

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

    streamController = StreamController.broadcast();
    streamController.stream.listen((player) {
      allPlayers.add(player);
      _updateSearchResults();
    });

    load(streamController);
  }

  void _updateSearchResults() => setState(() {
    filteredPlayers = allPlayers
      .where((player) => player.alias.startsWith(_searchController.text))
      .toList();
  });

  @override
  Widget build(Buildcontext context) {
    return ...
      TextField(
        controller: _searchController,
        decoration: InputDecoration(
          contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
          hintText: 'Search for player...',
          prefixIcon: Icon(Icons.search),
          suffixIcon: IconButton(
          onPressed: () {
            _updateSearchResults();
            _searchController.clear();
          },
          icon: Icon(Icons.close),
        ),
        border: OutlineInputBorder(borderRadius: BorderRadius.circular(30.0)),
      ),
      ...
      GridView.builder(
        ...
        itemCount: filteredPlayers.length,
        itemBuilder: (_, int index) {
          final player = filteredPlayers[index];

          return ProPlayerItem(
            player: player,
            goToDetail: () => {},
            goToSteam: () => _launchURL(player.profileUrl),
          );
        }
      )
    ...;
  }
}

关于dart - 监听 StreamingController 并更新列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52836289/

相关文章:

flutter - flutter/dart : Any downsides to async/await vs. raw Future API 中的异步模式?

dart - 如何在 flutter 中生成以太坊地址?

android - 我该如何解决 The method 'toMap' was called on null?

flutter - 波纹动画 flutter

firebase - Flutter Firebase如何获取随机文档

regex - 正则表达式匹配忽略“\”的字符串

flutter - 如何通过共享的首选项将初始值设置为文本字段

dart - 如何在 ListTile 中添加 AlertDialog

dart - 如何设置CrossAxisAlignment的值?

android - 测试奖励广告未显示 - 广告无法加载 : LoadAdError(code: 3, 域 : com. google.android.gms.ads,消息 : No ad config.