flutter - 可以在 ChangeNotifier 子类中使用 onPressed 函数吗

我正在使用提供程序进行状态管理,并且我在 ChangeNotifier 子类的函数中给了 onTap 一个 value 但我的应用程序没有响应,我的意思是,当我点击小部件时,它不会更新状态,但是,它确实改变了 values 我需要它来改变,我知道这是因为我在 onTap 函数中调试打印,当我点击时,它实际上打印出按钮被点击,但状态没有更新,小部件仍然是在我热重启之前都是一样的,然后它会更新所有内容,即使热重载也不会更新它,这是功能

class Storage extends ChangeNotifier{

  static const _storage =  FlutterSecureStorage();
  static const _listKey = 'progress';
  List _dataMaps = [];
  List<DayTile> dayTileMain = [];

  void createDataMap() {
    for (int i = 1; i < 101; i++) {
      final data = Data(number: i).toJson();
      _dataMaps.add(data);
    }
  }

  void createDayTiles() {
    for(Map<String, dynamic> data in _dataMaps) {
      bool isDone = data['i'];
      final dayTile = DayTile(
        number: data['n'],
        isDone: isDone,
        // This is where i need to rebuild the tree
        onTap: () async {
          data['i'] = true;
          notifyListeners();
          print(data['i']);
          print(isDone);
          await writeToStorage();
        },
      );
      dayTileMain.add(dayTile);
    }
    print('data tiles created');
  }
}

这是 DayTile 类

class DayTile extends StatelessWidget {
  const DayTile({
    Key? key,
    required this.number,
    required this.isDone,
    required this.onTap,
  }) : super(key: key);

  final int number;
  final VoidCallback onTap;
  final bool isDone;


  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        height: 50,
        width: MediaQuery.of(context).size.width * .15,
        decoration: BoxDecoration(
          color: !isDone
              ? const Color(0xffedecea)
              : const Color(0xffedecea).withOpacity(0.1),
          borderRadius: BorderRadius.circular(5),
        ),
        child: Center(
          child: Stack(
            alignment: Alignment.center,
            children: [
              Center(
                child: Text(
                  number.toString(),
                  style: const TextStyle(
                    color: Color(0xff576aa4),
                  ),
                ),
              ),
              Visibility(
                visible: isDone,
                child: const Divider(
                  color: Colors.black,
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

这是我聆听变化的地方

Wrap(
      spacing: 13,
      runSpacing: 13,
      children: Provider.of<Storage>(context).dayTileMain,
   ),

data['i'] 为真时,它应该更新它在循环中打开的 DayTile() 的当前实例,并且在 DayTile() 中我使用 data['i'] 的 value 来设置 bool isDone 的 value 和取决于 isDone 是真还是假,小部件的颜色会改变和其他一些东西,但是,它们不会改变 onTap,但是在我热重启后它们会改变,当它读取存储并恢复保存的数据时,可以secureStorage 写入存储的同时会受到影响吗?

回答1

我解决了它,结果发现在模型类中监听事件不是一个好主意,它不会监听,所以我没有在模型类中生成小部件列表,而是将它移到那里,而是在里面生成它wrap 小部件,而不是在模型类中侦听列表,我只是在我的 wrap 中有列表,如果它是我尝试生成的列表视图,我最初会使用 ListView.builder() 我没有'不知道你可以在 wrap 小部件的子项中生成一个列表,所以我只是坚持在模型中定义它,我遇到了这个堆栈问题 https://stackoverflow.com/q/58547544/17971158 这就是我知道如何在 children 属性中构建小部件的方式,我实际上只是在寻找 Wrap 小部件的 ListView.builder() 版本,所有人都说,这就是我的东西的样子

模型

class Storage extends ChangeNotifier {
  static const _storage = FlutterSecureStorage();
  static const _listKey = 'progress';
  List _dataMaps = [];
  List<DayTile> dayTileMain = [];

  void createDataMap() {
    for (int i = 1; i < 101; i++) {
      final data = Data(number: i).toJson();
      _dataMaps.add(data);
    }
  }

  int get listLength {
    return _dataMaps.length;
  }

  UnmodifiableListView get dataMaps {
    return UnmodifiableListView(_dataMaps);
  }

  void pressed(Map<String, dynamic> map) async {
    map['i'] = true;
    await writeToStorage();
    notifyListeners();
  }


  Future writeToStorage() async {
    final value = json.encode(_dataMaps);
    await _storage.write(key: _listKey, value: value);
  }

  Future<void> getTasks() async {
    print('getTasks called');
    final value = await _storage.read(key: _listKey);
    final taskList = value == null ? null : List.from(jsonDecode(value));
    if (taskList == null) {
      print('getTasks is null');
      createDataMap();
      // createDayTiles();
    } else {
      print('getTasks is not null');
      print(taskList);
      _dataMaps = taskList;
      // createDayTiles();
    }
  }

  Future readFromStorage() async {
    await getTasks();
    notifyListeners();
  }
}

包装生成器

class DayTiles extends StatelessWidget {
  const DayTiles({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Consumer<Storage>(
      builder: (_, storageData, __) => Wrap(
        spacing: 13,
        runSpacing: 13,
        children: [
          for(Map<String, dynamic> data in storageData.dataMaps)
            DayTile(
              number: data['n'],
              onTap: () {
                storageData.pressed(data);
              },
              isDone: data['i'],
            ),
        ],
      ),
    );
  }
}

而不是使用包装并在屏幕类中侦听对其子项的更改,我只是直接使用我创建的 DayTiles() 自定义小部件

相似文章

随机推荐

最新文章