Search code examples
flutterflutter-state

Flutter change state on all list item


Hey I am a newbie in flutter, I am trying to build an interview radio app

The issue I am facing is when changing state on switching music from one station to another, the "playing" and icon still don't change for the previously clicked object, but the new station starts playing

Here the station has switched but playing has not yet gone

Here the station has switched but playing text has not yet gone, as well as the icon changed

Ideally, I want when switched, the playing and icon change should be switched to the one playing now, and one that's switched from should have icon showing as the rest

My code

class ItemWidget extends StatefulWidget {
  final Item item;

  ItemWidget({Key? key, required this.item}) : super(key: key);

  @override
  State<ItemWidget> createState() => _ItemWidgetState();
}

class _ItemWidgetState extends State<ItemWidget> {
  static AudioPlayer player = AudioPlayer();
  static String name = "";
  static bool isPlaying = false;
  static String error = '';

  initRadioPlayer(namepassed, url) async {
    try {
      if (name == namepassed) {
        player.stop();
        name = "";
        isPlaying = false;
        setState(() {});
      } else if (name != namepassed) {
        if (isPlaying == true) {
          await player.stop();
        }
        await player.setUrl(url);
        player.play();
        name = namepassed;
        isPlaying = true;
        setState(() {});
      }
    } catch (err) {
      error = err.toString();
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      child: ListTile(
        onTap: () {
          initRadioPlayer(widget.item.name, widget.item.url);
        },
        title: Text(widget.item.name),
        subtitle: name == widget.item.name
            ? isPlaying
                ? Text('Playing')
                : Text('')
            : Text(''),
        trailing: Icon(isPlaying
            ? name == widget.item.name
                ? CupertinoIcons.stop_circle
                : CupertinoIcons.play_circle
            : CupertinoIcons.play_circle),
        textColor: Color.fromARGB(255, 31, 22, 22),
      ),
    );
  }
}

Solution

  • I used a callback function and kept the state of which one is playing in the parent just like Ivo Becker suggested:

    void _update(String name, bool isPlaying) {
      setState(() {
        _name = name;
        _isPlaying = isPlaying;
      });
    }
    

    This goes in the parent and then is passed on to and called from the child:

    class ItemWidget extends StatefulWidget {
      final Item item;
      final String name;
      final bool isPlaying;
      Function callback;
    

    and on tap you call it:

    widget.callback(station_name, true);