Search code examples
flutterdartinfinite-looppopupmenu

Suspicion of infinite loop using Riverpod & PopupMenuButton


I've racked my brains looking for my error but I can't find it. Looking for assistance.

I'm using Riverpod for dependency injection here. Got some sort of infinite loop running once I navigate to screen with a PopupMenuButton. The issue is related to my design of the menu button because if I remove it all is well. With the button my CPU skyrockets, without, it's completely normal.

I've tried inserting print() statements everywhere looking for repeating code but I'm at a loss for where Ive got a problem...

Can anyone see what is going on here?

Service Class

class AppStateService extends ChangeNotifier {
List<String> saleSources = [];
late String? selectedSaleSource;

Future<void> addSaleSource(String salesPerson) async {
    Box<String> salesSourcesBox = await Hive.openBox<String>(kBoxSaleSource + '_' + authorizedLocalUser!.userID);
    await salesSourcesBox.add(salesPerson);
    saleSources = salesSourcesBox.values.toList();
    print('1');
    notifyListeners();
  }

  Future<void> saleSourceLogic() async {
    Box<String> salesSourcesBox = await Hive.openBox<String>(kBoxSaleSource + '_' + authorizedLocalUser!.userID);
    if (salesSourcesBox.values.toList().isEmpty) await salesSourcesBox.add('Add source');
    if (salesSourcesBox.values.contains('Add source') && salesSourcesBox.values.toList().length > 1) await salesSourcesBox.deleteAt(0);
    saleSources = salesSourcesBox.values.toList();
    print('2');
    notifyListeners();
  }

  Future<void> getSaleSources() async {
    Box<String> salesSourcesBox = await Hive.openBox<String>(kBoxSaleSource + '_' + authorizedLocalUser!.userID);
    saleSources = salesSourcesBox.values.toList();
    print('3');
    notifyListeners();
  }

  void setSaleSource(String source) {
    print('4');
    selectedSaleSource = source;
    notifyListeners();
  }
}

Widget

class SalesSourcePulldownMenuWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    context.read(appState).saleSourceLogic();
    context.read(appState).getSaleSources();
    List<String> listItems = context.read(appState).saleSources;
    late List<PopupMenuItem<String>> menuItems;

    menuItems = listItems
        .map((String value) => PopupMenuItem<String>(
              value: value,
              child: Text(value),
            ))
        .toList();

    return PopupMenuButton<String>(
        itemBuilder: (BuildContext contect) => menuItems,
        onSelected: (String newValue) {
          context.read(appState).setSaleSource(newValue);
        });
  }
}

Screen Snippet

...

TextField(
                    controller: salesPerson,
                    keyboardType: TextInputType.text,
                    textCapitalization: TextCapitalization.words,
                    autocorrect: false,
                    decoration: InputDecoration(
                      border: OutlineInputBorder(borderSide: BorderSide(color: Colors.black)),
                      labelText: 'Name',
                      suffixIcon: SalesSourcePulldownMenuWidget(),
                    ),
                  ),

...


Solution

  • I just figured out that the cause of the loop-like issue is having my PopupMenuButton inside my text field as a suffix icon. Will need to redesign outside textField.

    I do not know any technical specifics as to what could have caused this further than the fact that taking it out of the textField fixes the resource drain.

    I'll leave this here in case anyone else encounters this and it may help. Or in case anyone else can explain the reason for resource drain better.