Why do I keep getting ‘Instance of…’ when I’m trying to get a String. What’s wrong with the function?
Future<string?> counter() async {
Future.delayed(const Duration(seconds: 5), () {
context.watch<FoodCount>().display(widget.food).toString();
return widget.food.quantity.toString();
});
int count = widget.food.quantity;
// print(count);
return count;
}
This is what I’m trying to do:
class FoodQuantity extends StatefulWidget {
final Food food;
FoodQuantity(this.food);
@override
State<FoodQuantity> createState() => _FoodQuantityState();
}
class _FoodQuantityState extends State<FoodQuantity> {
final int amount = 0;
String getCurrency() {
var format = NumberFormat.simpleCurrency(name: 'NGN');
return format.currencySymbol;
}
Future<int> counter() async {
final int result = await Future.delayed(const Duration(seconds: 5), () {
int result = context.read<FoodCount>().display(widget.food);
return result;
});
return result;
}
@override
Widget build(BuildContext context) {
return Container(
width: double.maxFinite,
height: 40,
child: Stack(
children: [
Align(
alignment: const Alignment(-1, 0), //0.3
child: Container(
width: 120,
height: double.maxFinite,
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(30),
),
child: Row(
children: [
const SizedBox(width: 15), //Spacing
Text(
getCurrency(),
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
Text(
widget.food.price.toString(),
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
)
],
),
),
),
Align(
alignment: const Alignment(1, 0), //0.3
child: Container(
height: double.maxFinite,
width: 120,
decoration: BoxDecoration(
color: Color(0xff453658),
borderRadius: BorderRadius.circular(30),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
GestureDetector(
onTap: () {
if (context.read<Counter>().count != 0) {
context.read<Counter>().decrement();
// widget.food.quantity--;
userOrders.remove(widget.food);
context.read<FoodCount>().decrement(widget.food);
setState(() {});
} else {
context.read()<Counter>();
}
},
child: const Text(
'-',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: const EdgeInsets.all(12),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
child: Text(
counter().toString(),
// context
// .watch<FoodCount>()
// .display(widget.food)
// .toString(),
// widget.food.quantity.toString(),
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
),
GestureDetector(
onTap: () {
context.read<Counter>().increment();
context.read<FoodCount>().increment(widget.food);
// widget.food.quantity++;
userOrders.add(widget.food);
setState(() {});
},
child: const Text(
'+',
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
],
),
);
}
}
I made a provider class FoodCount
that monitors the value quantity
of object type Food
. The async function is supposed to simply return the quantity
of the Food
provided to it
Provider:
class FoodCount with ChangeNotifier {
int increment(Food food) {
food.quantity++;
int foodCount = food.quantity;
notifyListeners();
return foodCount;
}
int decrement(Food food) {
food.quantity--;
int foodCount = food.quantity;
notifyListeners();
return foodCount;
}
int display(Food food) {
int count = food.quantity;
notifyListeners();
return count;
}
void update() {
notifyListeners();
}
}
Food:
class Food {
String imgUrl;
String desc;
String name;
String waitTime;
num score;
int price;
int quantity;
bool favourited;
List<Map<String, String>> ingredients;
String about;
bool highlight;
Food(this.imgUrl, this.desc, this.name, this.waitTime, this.score, this.price,
this.quantity, this.ingredients, this.about, this.favourited,
{this.highlight = false});
}
3
Answers
Future.delayed is by itself a
Future
, so you cannot track it without anawait
to keep the result.Take a look here, how you can make it, then take care of the difference about a sequential method and a Future method;
Or
When you work with Future and you want to get value from it, you should use await or then()
try to use this code:
First off, here’s a tip: you’re using
Future.delayed
as a way to get a value after a delay. Try splitting that up into two parts. Instead ofTry
Secondly, the other users are right: when you receive a
Future<String>
, you can’t actually get to theString
withoutawait
ing it. Problem is, you can useawait
in anasync
function, andbuild
is notasync
. Conceptually, think of it as "you need to wait 5 seconds for the delay, but your user needs a UI now".You can solve this using
FutureBuilder
, which allows you to return some widget until the future finishes.