I'm doing the flutter baby names codelab and am implementing the transaction to firestore to remedy race conditions. If I spam a name it will result in missed votes and a IllegalStateException.
I want to disable the ListTile from within the onTap as the transaction is being completed and then re-enable it after transaction update.
I tried setting state from within the transaction and that did not work. The code is below.
child: ListTile(
title: Text(record.name),
trailing: Text(record.votes.toString()),
onTap: () => Firestore.instance.runTransaction((transaction) async {
final freshSnapshot = await transaction.get(record.reference);
final fresh = Record.fromSnapshot(freshSnapshot);
await transaction.update(record.reference, {'votes': fresh.votes + 1});
///DOES NOT WORK
setState(() {
enabled: false
});
///
}),
I tried one of the suggestions here but that does not work either. It seems as though the state of the _isEnableTile boolean gets reset even though I never set it back to true. One way that kinda works is by setting _isEnableTile as a feild (i.e on the class level) unfortunately this results in all listtiles being disabled via the 'enabled' parameter.
Widget _buildListItem(BuildContext context, DocumentSnapshot data) {
bool _isEnableTile = true;
final record = Record.fromSnapshot(data);
return Padding(
key: ValueKey(record.name),
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(5.0),
),
child: ListTile(
title: Text(record.name),
trailing: Text(record.votes.toString()),
onTap: () async {
print(_isEnableTile);
if (_isEnableTile) {
_isEnableTile = false;
print('doing it');
await Firestore.instance.runTransaction((transaction) async {
final freshSnapshot = await transaction.get(record.reference);
final fresh = Record.fromSnapshot(freshSnapshot);
await transaction
.update(record.reference, {'votes': fresh.votes + 1});
});
} else {
print('hmmm not doing it');
}
},
),
),
);
}
The expected behaviour of above code is to be able to tap once and then never be able to tap again since _isEnableTile is never switched back to true. This is not the case. _isEnableTile is reset to true constantly (most probably as soon as the onTap is complete).
EDIT: Unfortunately, you cannot use enabled to switch the enabled state because it is final inside ListTile for some reason.
bool _isEnableTile = true;outside build function. - anmol.majhail