Home > Net >  Flutter ListView builder not updating with fresh data
Flutter ListView builder not updating with fresh data

Time:09-17

I'm running a search filter function which retrieves players from a Floor DB. The functionality works fine and I can see through logs that the new player are returned, however my UI won't update which seems to be from the new list i assign not triggering a re-render.

Can anyone see what's wrong with my code?

    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);
    });
  }
}

CodePudding user response:

Because your put ListView.builder in Dialog it will create a new stack and a new stack can't rerender from another stack

You can change your code with create a new stateful widget for dialogs

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;
  }

}
  
  • Related