我正在使用提供程序进行状态管理,并且我在 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()
自定义小部件