I am using provider for state management, and I've given onTap a value in a function in the ChangeNotifier child class but my app is unresponsive, I mean, when i tap on the widget, it doesn't update state, however, it does change the values i need it to change tho, i know this coz I am debugPrinting in the onTap function and when i tap, it actually prints that the button got tapped, but state doesn't update, widget remains the same until i hot restart, then it updates everything, even hot reload doesn't update it, here's the function
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');
}
}
and here is the DayTile class
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,
),
),
],
),
),
),
);
}
}
here is where I listen for the change
Wrap(
spacing: 13,
runSpacing: 13,
children: Provider.of<Storage>(context).dayTileMain,
),
when data['i']
is true, it should update the current instance of DayTile() that it's on in the loop, and in DayTile()
I use the value of data['i']
to set the value of bool isDone
and depending on whether isDone is true or false, the color of the widget changes and some other things, BUT, they don't change onTap, but they change after I hot restart, when it's read the storage and restored the saved data, could the secureStorage writing to storage at the same time be affecting it?
I solved it, turns out it's not a good idea to listen for events in the model class, it won't listen, so instead of generating the list of widgets in the model class, I moved it outta there, and instead generated it inside the wrap widget, and instead of listening for a list in the model class, i just had the list there in my wrap, if it was a listview i was tryna generated, i would've done this initially with a
ListView.builder()
i didn't know you could generate a list inside the children of the wrap widget, so i just stuck to defining it in the model, I came across this stack question Flutter: How to use Wrap instead of ListView.builder? and that's how i knew how to build widgets inside a children property, i was actually just looking for aListView.builder()
version for the Wrap widget, all said, this is what my stuff is looking likeModel
Wrap Builder
and instead of using a wrap and listening for changes to it's children in the screen class, i just directly use the
DayTiles()
custom widget i created