Reputation: 7128
I have list of items that are loading from database, the problem is each one of this items require to get 1 string loaded from server and I can't find out a way to make that string get updates.
Logic
Screenshot
Code Commented
Padding(
padding: const EdgeInsets.symmetric(vertical: 1.0, horizontal: 4.0),
child: ListView.builder(
itemCount: locations.length,
itemBuilder: (context, index) {
WorldTime instance = WorldTime(name: locations[index].name, country: locations[index].country, wikipedia: locations[index].wikipedia, location: locations[index].location, flag: locations[index].flag);
// need to use await but async/await is not allowed under `Widget build(BuildContext context)`
instance.getTime();
var time = instance.time;
return Card(
child: ListTile(
onTap: () {},
title: Text('${locations[index].location}'),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(locations[index].country),
SizedBox(height: 5.0),
Text('$time'), // <-- show updated time (currently only show first load `null` and never gets updated).
],
),
leading: CircleAvatar(
backgroundImage: AssetImage('assets/${locations[index].flag}'),
),
),
);
},
),
),
PS:
Regarding to instance.getTime()
in case you doubt that problem might be from there, I need to assure you that instance.getTime()
works absolutely fine in all other screens that I have and here is console log screenshot of it in this particular list items which proves the data are loaded but not show in view (it loads after database list because it needs to get time from server).
Question
How can I add time into my list items with some sort of delay? (best if be possible to use async/await
)
Update
class WorldTime {
String location; // location name for the UI
String time; // the time in that location
String flag; // url to an asset flag icon
String country;
String wikipedia;
String name; // name of the location to get data from server
bool isDaytime; // true or false if day time or not
WorldTime({this.location, this.country, this.wikipedia, this.flag, this.name});
Future<void> getTime() async {
var apiUrl = Uri.https('example.com', 'api/timezone', {'name': '$name'});
// Await the http get response, then decode the json-formatted response.
var response = await http.get(apiUrl);
if (response.statusCode == 200) {
var jsonResponse = convert.jsonDecode(response.body) as Map<String, dynamic>;
// get properties from data
DateTime dateTime = DateTime.now().toUtc();
String offset = jsonResponse['data']['offset'].substring(1, 3);// 07 (hour)
String positive = jsonResponse['data']['offset'].substring(0, 1); // determine is positive or negative offset
// create Datetime object
String now1 = DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
DateTime now = DateTime.parse(now1);
if(positive == '+') {
now = now.add(
Duration(
hours: int.parse(offset),
minutes: int.parse(jsonResponse['data']['offset'].substring(4, 6)) // 00 (minutes)
)
);
} else {
now = now.subtract(
Duration(
hours: int.parse(offset),
minutes: int.parse(jsonResponse['data']['offset'].substring(4, 6)) // 00 (minutes)
)
);
}
print(now); //2021-05-25 09:57:08.000
// set the time property
isDaytime = now.hour > 5 && now.hour < 18 ? true : false;
time = DateFormat.jm().format(now);
} else {
print('Request failed with error: ${response.statusCode}.');
isDaytime = false;
time = 'Could not get time data';
}
}
}
Upvotes: 0
Views: 519
Reputation: 5736
Use FutureBuilder for calling instance.getTime() since it returns a Future. Replace Text('$time')
with following:
FutureBuilder(
future: instance.getTime(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done && instance.time != null) {
return Text(instance.time.toString());
}
return Text('No Data');
},
),
Since getTime
returns the void
& assigns time
to WorldTime
instance, use instance
inside the if
condition.
Upvotes: 1