ChangeNotifier 的消费者状态未更新

问题描述 投票:0回答:1

当子组件更改状态时,使用通知程序的组件不会更新

state_provider.dart

class StateProvider extends ChangeNotifier {
  // user data
  String _name = '';
  String _phoneNumber = '';
  String _email = '';
  String? _gender;
  String _locationSerachText = '';
  Map<String, dynamic> _viewPort = {};
  final List<String> _tags = [];
  List<LocationCard> _locationCards = [];

  // Getters for user data
  String get name => _name;
  String get phoneNumber => _phoneNumber;
  String get email => _email;
  String? get gender => _gender;
  Map<String, dynamic> get viewPort => _viewPort;
  String get locationSerachText => _locationSerachText;
  List<String> get tags => _tags;
  List<LocationCard> get locationCards => _locationCards;

  // Setters for user data
  set name(String value) {
    _name = value;
    notifyListeners();
  }

  set viewPort(Map<String, dynamic> value) {
    _viewPort = value;
    notifyListeners();
  }

  set locationSerachText(String value) {
    _locationSerachText = value;
    notifyListeners();
  }

  set locationCards(List<LocationCard> value) {
    _locationCards = value;
    notifyListeners();
  }

  set phoneNumber(String value) {
    _phoneNumber = value;
    notifyListeners();
  }

  set email(String value) {
    _email = value;
    notifyListeners();
  }

  set gender(String? value) {
    _gender = value;
    notifyListeners();
  }

  // Method to add tag
  void addTag(String tag) {
    _tags.add(tag);
    notifyListeners();
  }

  // Method to remove tag
  void removeTag(String tag) {
    _tags.remove(tag);
    notifyListeners();
  }

}

powerup_profile_screen.dart

class PowerUpProfileScreen extends StatefulWidget {
  @override
  _PowerUpProfileScreenState createState() => _PowerUpProfileScreenState();
}

class _PowerUpProfileScreenState extends State<PowerUpProfileScreen> {
  @override
  Widget build(
    BuildContext context,
  ) {
    final stateProvider = Provider.of<StateProvider>(context, listen: true);

    bool isAtLeastOneTagSelected() {
      return stateProvider.tags.isNotEmpty;
    }

    Color getFinishButtonColor() {
      return isAtLeastOneTagSelected() ? Colors.blue : Colors.grey;
    }

    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: SvgPicture.asset('assets/icons/back-arrow.svg'),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
        actions: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 100.0),
            child: buildDotsDecorator(
              2,
              List.generate(3, (index) => 'Page $index'),
            ),
          )
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 5.0),
        child: Container(
          color: GuideroTheme.darkTheme.primaryColor,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const CustomHeaderText(text: 'Power up your profile'),
              const SizedBox(
                height: 12,
              ),
              const ParagrapghText(
                text: 'Choose tags that match your expertise and interests',
                fontSize: 16,
                textAlign: TextAlign.left,
              ),
              const SizedBox(
                height: 16.0,
              ),
              const ParagrapghText(
                text: 'You can select more than one tag',
                fontSize: 16,
                textAlign: TextAlign.left,
              ),
              const SizedBox(
                height: 32.0,
              ),
              buildTagCards([
                'Cafes & Pubs',
                'Resorts',
                'Hotels',
                'Social Events',
                'Tourist Spots'
              ]),
              const Spacer(),
              Padding(
                padding: const EdgeInsets.only(bottom: 8.0),
                child: CustomTextButton(
                  text: 'Finish',
                  onPressed: isAtLeastOneTagSelected()
                      ? () {
                          print("finish clicked ");
                        }
                      : null,
                  backgroundColor: getFinishButtonColor(),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  Widget buildTagCards(List<String> tagTexts) {
    return Wrap(
      spacing: 30.0,
      runSpacing: 16.0,
      alignment: WrapAlignment.start,
      children: tagTexts.map((tagText) {
        return TagCard(
          tagText: tagText,
        );
      }).toList(),
    );
  }
}

在 TagCard 小部件内,可以添加和删除标签 👇🏽

class TagCard extends StatefulWidget {
  final String tagText;

  TagCard({Key? key, required this.tagText}) : super(key: key);

  @override
  State<TagCard> createState() => _TagCardState();
}

class _TagCardState extends State<TagCard> {
  bool isSelected = false;

  @override
  Widget build(BuildContext context) {
    final stateProvider = Provider.of<StateProvider>(context);

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(99),
        border: Border.all(
            color: isSelected ? Colors.white : Colors.white.withOpacity(0.5),
            width: 1),
        color: Colors.transparent,
      ),
      child: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          GestureDetector(
            onTap: () {
              isSelected = stateProvider.tags.any(
                  (tag) => tag.toLowerCase() == widget.tagText.toLowerCase());
              print('Tag tapped: ${widget.tagText}');
              print('Tag selected: $isSelected');
              if (isSelected) {
                stateProvider.tags.remove(widget.tagText);
              } else {
                stateProvider.tags.add(widget.tagText);
              }
              setState(() {
                isSelected = !isSelected;
              });
              print("other tags ${stateProvider.viewPort}");
              print('Selcted tags : ${stateProvider.tags}');
            },
            child: Text(
              widget.tagText,
              style: const TextStyle(
                  color: Colors.white,
                  fontSize: 16.0,
                  fontWeight: FontWeight.w500),
            ),
          ),
        ],
      ),
    );
  }
}

按钮颜色相应改变👇🏽

final stateProvider = Provider.of<StateProvider>(context, listen: true);

bool isAtLeastOneTagSelected() {
   return stateProvider.tags.isNotEmpty;
}

Color getFinishButtonColor() {
   return isAtLeastOneTagSelected() ? Colors.blue : Colors.grey;
}

当选择/删除标签时,状态不会反映在父组件中。 如何解决这个问题💁🏽u200d♂️

尝试直接获取值

backgroundColor: stateProvider.tags.isNotEmpty ? Colors.blue : Colors.grey;
flutter dart state flutter-change-notifier
1个回答
0
投票

我会简化你的

TagCard
小部件,并与 Flutter 中具有类似行为的许多其他小部件一样(
CheckBox
Switch
Radio
,...),使其不保持任何状态。相反,当
TagCard
的状态需要更改时,小部件会调用 [onSelect] 或 [onDeselect] 回调,并且使用标签卡的小部件将侦听回调,相应地更新状态并使用新值重建复选框更新标签卡的视觉外观。

class TagCard extends StatelessWidget {
  final String tagText;

  final bool isSelected;

  final VoidCallback onSelect;
  final VoidCallback onDeselect;

  TagCard({Key? key, required this.tagText,required this.isSelected,  required this.onSelect, required this.onDeselect,}) : super(key: key);


  @override
  Widget build(BuildContext context) {

    return Container(
      ...
          GestureDetector(
            onTap: () {
              isSelected ? onDeselect() : onSelect();
            },
            child: Text(
              tagText,
          ...
  }
}
Widget buildTagCards(final stateProvider, List<String> tagTexts) {
  return Wrap(
    spacing: 30.0,
    runSpacing: 16.0,
    alignment: WrapAlignment.start,
    children: tagTexts.map((tagText) {
      return TagCard(
        tagText: tagText,
        isSelected: stateProvider.tags.contains(tagText),
        onSelect: () => stateProvider.tags.add(tagText),
        onDeselect: () => stateProvider.tags.remove(tagText),
      );
    }).toList(),
  );
}
© www.soinside.com 2019 - 2024. All rights reserved.