最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

dart - Why is my UI not updating in Flutter with MobX @observable variables when using Observer? - Stack Overflow

programmeradmin0浏览0评论

I created the following observable variables:

   ```  @observable
  ObservableList<bool> optionsSelecteds = ObservableList<bool>();

  @observable
  ObservableList<String> labelSelecteds = ObservableList<String>();
  @observable
  String selectedOption = '';
```

and on my page I call the following widget:

```Observer(
                builder: (context) {
                  return SingleChildScrollView(
                    child: widget.options!.isNotEmpty
                        ? ListView.builder(
                            shrinkWrap: true,
                            itemCount: widget.options!.length,
                            itemBuilder: (context, index) {
                              return QuizzOptionButtons(
                                title: widget.options![index],
                                onTap: () {
                                  controller.ChangeSelectedOptions(
                                      widget.options![index]);
                                  controller.onSelect(index, widget.options!,
                                      widget.isMultipleChoice!);
                                  debugPrint(widget.options![index]);
                                  debugPrint(
                                      controller.optionsSelecteds.toString());
                                  debugPrint(
                                      controller.labelSelecteds.toString());
                                },
                                isSelected: controller.optionsSelecteds[index],
                                isMultipleChoice: widget.isMultipleChoice!,
                                options: widget.options,
                                index: index,
                              );
                            },
                          )
                        : const Center(child: Text('Nenhuma opção disponível')),
                  );
                },
              ),```

```

Basically I'm mapping buttons for a quiz. My actions are:

  ```@action
  void isSelectedList(List<dynamic> options, bool isMultipleChoice) {
    optionsSelecteds.clear();
    labelSelecteds.clear();
    if (options.isNotEmpty) {
      for (var element in options) {
        labelSelecteds.add('');
        optionsSelecteds.add(false);
      }
    }
  }

  @action
  void onSelect(int index, List<dynamic> options, bool isMultipleChoice) {
    optionsSelecteds[index] = !optionsSelecteds[index];
    labelSelecteds[index] == ''
        ? labelSelecteds[index] = selectedOption
        : labelSelecteds[index] = '';
    for (int i = 0; i < optionsSelecteds.length; i++) {
      if (i == index) {
        optionsSelecteds[i] = true;
        selectedOption = options[index];
      } else {
        optionsSelecteds[i] = false;
        labelSelecteds[i] = '';
      }
    }
  }

  @action
  void ChangeSelectedOptions(String option) {
    selectedOption = option;
  }```

and my complete widget looks like this:

```import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_modular/flutter_modular.dart';

import '../controller/quizz_store.dart';

class QuizzOptionButtons extends StatefulWidget {
  final String title;
  final bool isSelected;
  final List<dynamic>? options;
  final int index;
  final VoidCallback onTap;
  final bool isMultipleChoice;

  const QuizzOptionButtons({
    Key? key,
    required this.title,
    required this.isSelected,
    required this.onTap,
    this.isMultipleChoice = false,
    required this.options,
    required this.index,
  }) : super(key: key);

  @override
  _QuizzOptionButtonsState createState() => _QuizzOptionButtonsState();
}

class _QuizzOptionButtonsState extends State<QuizzOptionButtons> {
  final controller = Modular.get<QuizzStore>();

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: widget.onTap,
      child: Container(
        width: double.infinity,
        padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20),
        margin: const EdgeInsets.symmetric(vertical: 8),
        decoration: BoxDecoration(
          color: widget.isSelected ? Colors.green : const Color(0xFF111827),
          borderRadius: BorderRadius.circular(16),
          border: Border.all(
            color: widget.isSelected ? Colors.green.shade300 : Colors.grey,
            width: 2,
          ),
          boxShadow: [
            BoxShadow(
              color: Colors.black.withOpacity(0.1),
              blurRadius: 5,
              offset: const Offset(0, 2),
            )
          ],
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(
              widget.title,
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                color: widget.isSelected ? Colors.white : Colors.white,
              ),
            ),
            if (widget.isMultipleChoice)
              Icon(
                widget.isSelected
                    ? Icons.check_circle
                    : Icons.check_circle_outline,
                color: widget.isSelected ? Colors.white : Colors.grey,
              ),
          ],
        ),
      ),
    );
  }
}```

I've literally been trying to figure out why my UI won't update for 4 hours, what am I doing wrong? What's the correct way to do this?

I created the following observable variables:

   ```  @observable
  ObservableList<bool> optionsSelecteds = ObservableList<bool>();

  @observable
  ObservableList<String> labelSelecteds = ObservableList<String>();
  @observable
  String selectedOption = '';
```

and on my page I call the following widget:

```Observer(
                builder: (context) {
                  return SingleChildScrollView(
                    child: widget.options!.isNotEmpty
                        ? ListView.builder(
                            shrinkWrap: true,
                            itemCount: widget.options!.length,
                            itemBuilder: (context, index) {
                              return QuizzOptionButtons(
                                title: widget.options![index],
                                onTap: () {
                                  controller.ChangeSelectedOptions(
                                      widget.options![index]);
                                  controller.onSelect(index, widget.options!,
                                      widget.isMultipleChoice!);
                                  debugPrint(widget.options![index]);
                                  debugPrint(
                                      controller.optionsSelecteds.toString());
                                  debugPrint(
                                      controller.labelSelecteds.toString());
                                },
                                isSelected: controller.optionsSelecteds[index],
                                isMultipleChoice: widget.isMultipleChoice!,
                                options: widget.options,
                                index: index,
                              );
                            },
                          )
                        : const Center(child: Text('Nenhuma opção disponível')),
                  );
                },
              ),```

```

Basically I'm mapping buttons for a quiz. My actions are:

  ```@action
  void isSelectedList(List<dynamic> options, bool isMultipleChoice) {
    optionsSelecteds.clear();
    labelSelecteds.clear();
    if (options.isNotEmpty) {
      for (var element in options) {
        labelSelecteds.add('');
        optionsSelecteds.add(false);
      }
    }
  }

  @action
  void onSelect(int index, List<dynamic> options, bool isMultipleChoice) {
    optionsSelecteds[index] = !optionsSelecteds[index];
    labelSelecteds[index] == ''
        ? labelSelecteds[index] = selectedOption
        : labelSelecteds[index] = '';
    for (int i = 0; i < optionsSelecteds.length; i++) {
      if (i == index) {
        optionsSelecteds[i] = true;
        selectedOption = options[index];
      } else {
        optionsSelecteds[i] = false;
        labelSelecteds[i] = '';
      }
    }
  }

  @action
  void ChangeSelectedOptions(String option) {
    selectedOption = option;
  }```

and my complete widget looks like this:

```import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:flutter_modular/flutter_modular.dart';

import '../controller/quizz_store.dart';

class QuizzOptionButtons extends StatefulWidget {
  final String title;
  final bool isSelected;
  final List<dynamic>? options;
  final int index;
  final VoidCallback onTap;
  final bool isMultipleChoice;

  const QuizzOptionButtons({
    Key? key,
    required this.title,
    required this.isSelected,
    required this.onTap,
    this.isMultipleChoice = false,
    required this.options,
    required this.index,
  }) : super(key: key);

  @override
  _QuizzOptionButtonsState createState() => _QuizzOptionButtonsState();
}

class _QuizzOptionButtonsState extends State<QuizzOptionButtons> {
  final controller = Modular.get<QuizzStore>();

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: widget.onTap,
      child: Container(
        width: double.infinity,
        padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20),
        margin: const EdgeInsets.symmetric(vertical: 8),
        decoration: BoxDecoration(
          color: widget.isSelected ? Colors.green : const Color(0xFF111827),
          borderRadius: BorderRadius.circular(16),
          border: Border.all(
            color: widget.isSelected ? Colors.green.shade300 : Colors.grey,
            width: 2,
          ),
          boxShadow: [
            BoxShadow(
              color: Colors.black.withOpacity(0.1),
              blurRadius: 5,
              offset: const Offset(0, 2),
            )
          ],
        ),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Text(
              widget.title,
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                color: widget.isSelected ? Colors.white : Colors.white,
              ),
            ),
            if (widget.isMultipleChoice)
              Icon(
                widget.isSelected
                    ? Icons.check_circle
                    : Icons.check_circle_outline,
                color: widget.isSelected ? Colors.white : Colors.grey,
              ),
          ],
        ),
      ),
    );
  }
}```

I've literally been trying to figure out why my UI won't update for 4 hours, what am I doing wrong? What's the correct way to do this?

Share Improve this question asked Mar 28 at 0:48 Yuri TrindadeYuri Trindade 11 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

Modify the onSelect method to reassign the ObservableList:

@action
void onSelect(int index, List<dynamic> options, bool isMultipleChoice) {
  // Create a copy of the list and modify it
  final updatedOptions = List<bool>.from(optionsSelecteds);
  final updatedLabels = List<String>.from(labelSelecteds);

  for (int i = 0; i < updatedOptions.length; i++) {
    if (i == index) {
      updatedOptions[i] = true;
      updatedLabels[i] = selectedOption;
      selectedOption = options[index];
    } else {
      updatedOptions[i] = false;
      updatedLabels[i] = '';
    }
  }

  // Reassign the lists to trigger UI updates
  optionsSelecteds = ObservableList.of(updatedOptions);
  labelSelecteds = ObservableList.of(updatedLabels);
}
发布评论

评论列表(0)

  1. 暂无评论