flutterdartwidgetpopupmenustatefulwidget

It is possible to preserve state of PopUpMenuButton?


enter image description here

Currently i am working on music app and according to my ui i have to display download, downloading progress and downloaded status shown inside popup menu item.But according to Popup menu button widget behaviour, it is dispose and unmounted.So when i closed popup menu item and again open the last status always display download instead of downloading.So it is possible to prevent popup menu button after close.

I tried callback functions, provider, getx, auto keep alive and also stateful builder but it is not working.


Solution

  • I am using ValueNotifier to preserve the download progress. To preserve the state you can follow this structure and use state-management property like riverpod/bloc

    class DTest extends StatefulWidget {
      const DTest({super.key});
    
      @override
      State<DTest> createState() => _DTestState();
    }
    
    class _DTestState extends State<DTest> {
      /// some state-management , also can be add a listener 
      ValueNotifier<double?> downloadProgress = ValueNotifier(null);
      Timer? timer;
      _startDownload() {
        timer ??= Timer.periodic(
          Duration(milliseconds: 10),
          (timer) {
            downloadProgress.value = (downloadProgress.value ?? 0) + .01;
            if (downloadProgress.value! > 1) timer.cancel();
          },
        );
      }
    
      @override
      void dispose() {
        timer?.cancel();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Column(
            children: [
              PopupMenuButton(
                itemBuilder: (context) {
                  return [
                    PopupMenuItem(
                      child: ValueListenableBuilder(
                        valueListenable: downloadProgress,
                        builder: (context, value, child) => InkWell(
                            onTap: value == null ? _startDownload : null,
                            child: Text("${value ?? "Download"}")),
                      ),
                    )
                  ];
                },
              )
            ],
          ),
        );
      }
    }