Adding phone number to contact in flutter/dart - android

I'm building a selectable checkbox contact list in flutter but if a contact has only an email and no number, an error is thrown. I want to create a loop to add a number of '99999' to the contacts phone number if they don't have one. Please can someone guide me with an explanation of what I should change to make this work? I have had a go, but I am quite new to flutter so I'm not completely certain on syntax etc...
Here is the part of the code that I am trying to put the function into.
setMissingNo()async {
Iterable<Contact> contactsToLoop = (await ContactsService.getContacts()).toList();
contactsToLoop.forEach((Contact) { contactsToLoop = []..add(Item.fromMap({'label': 'work', 'value': 99999})); });
}
//fetch contacts from setMissingNo
getAllContacts() async{
Iterable<Contact> _contacts = (await ContactsService.getContacts()).toList();
setState(() {
contacts = _contacts;
}
);
}
Here is my whole code
import 'package:flutter/material.dart';
// TODO: make it ask for permissions otherwise the app crashes
import 'package:contacts_service/contacts_service.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<Contact> contacts = [];
List<Contact> contactsFiltered = [];
TextEditingController searchController = new TextEditingController();
#override
void initState() {
super.initState();
getAllContacts();
searchController.addListener(() => filterContacts());
}
//remove the +'s and spaces from a phone number before its searched
String flattenPhoneNumber(String phoneStr) {
return phoneStr.replaceAllMapped(RegExp(r'^(\+)|\D'), (Match m) {
return m[0] == "+" ? "+" : "";
});
}
//loop and set all contacts without numbers to 99999, pass new list to getAllContacts
setMissingNo()async {
Iterable<Contact> contactsToLoop = (await ContactsService.getContacts()).toList();
contactsToLoop.forEach((Contact) { contactsToLoop = []..add(Item.fromMap({'label': 'work', 'value': 99999})); });
}
//fetch contacts from setMissingNo
getAllContacts() async{
Iterable<Contact> _contacts = (await ContactsService.getContacts()).toList();
setState(() {
contacts = _contacts;
}
);
}
//filtering contacts function to match search term
filterContacts() {
List<Contact> _contacts = [];
_contacts.addAll(contacts);
if (searchController.text.isNotEmpty) {
_contacts.retainWhere((contact) {
String searchTerm = searchController.text.toLowerCase();
String searchTermFlatten = flattenPhoneNumber(searchTerm);
String contactName = contact.displayName.toLowerCase();
bool nameMatches = contactName.contains(searchTerm);
if (nameMatches == true) {
return true;
}
if (searchTermFlatten.isEmpty) {
return false;
}
var phone = contact.phones.firstWhere((phn) {
String phnFlattened = flattenPhoneNumber(phn.value);
return phnFlattened.contains(searchTermFlatten);
}, orElse: () => null);
return phone != null;
});
setState(() {
contactsFiltered = _contacts;
});
}
}
final selectedContacts = Set<Contact>();
#override
Widget build(BuildContext context) {
bool isSearching = searchController.text.isNotEmpty;
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
AppBar(
title: Text('Create Group'),
),
Container(
child: TextField(
controller: searchController,
decoration: InputDecoration(
labelText: 'Search Contacts',
border: OutlineInputBorder(
borderSide: new BorderSide(
color: Theme.of(context).primaryColor
)
),
prefixIcon: Icon(
Icons.search,
color: Theme.of(context).primaryColor
)
),
),
),
Expanded( child: ListView.builder(
shrinkWrap: true,
itemCount: isSearching == true ? contactsFiltered.length : contacts.length,
itemBuilder: (context, index) {
Contact contact = isSearching == true ? contactsFiltered[index] : contacts[index];
//TODO: make it so when you clear your search, all items appear again & when you search words it works
return CheckboxListTile(
title: Text(contact.displayName),
subtitle: Text(
contact.phones.elementAt(0).value
),
value: selectedContacts.contains(contact),
onChanged: (bool value) {
if (value) {
selectedContacts.add(contact);
} else {
selectedContacts.remove(contact);
}
setState((){});
// TODO: add in function to add contact ID to a list
});
},
),
/*new Expanded(
child: Align(
alignment: Alignment.bottomLeft,
child: BottomNavigationBar(
currentIndex: _currentIndex,
items: const <BottomNavigationBarItem>[
//TODO: create new contact functionality to add someone by name + email
BottomNavigationBarItem(
icon: Icon(Icons.add),
title: Text('Add Contact'),
),
BottomNavigationBarItem(
icon: Icon(Icons.create),
title: Text('Create Group'),
),
],
onTap: (index) {
setState(() {
_currentIndex = index;
});
}
)
)
)*/
)
],
)
),
);
}
}

Updating all contacts listed on the device might take a long time depending on the size of the device's contact list. Add that the task is being done on the UI thread. You may want to consider using Isolate for the task to move away the load from the UI thread. If you can also provide the errors that you're getting, it'll help us get a picture of the issue.
Another thing is, the way you're approaching the issue might be impractical. Is it really necessary to write a placeholder phone number to the contacts? The issue likely stems from trying to fetch the number from a contact but the Object returns null. Perhaps you may want to consider only updating the phone number when the contact is selected.

Related

Flutter The method 'map' was called on null. Receiver: null error

I'm having this super annoying issue of being unable to grab and display a table from my server hosted on PhpmyAdmin. (I've managed to grab the data and have it printed in the console, but now that I'm trying to display it in a table I can't seem to get it working)
I've tried nulling my variables but I'm not really sure what the main culprit for this error is. Any help would be greatly appreciated.
Image of Error
data.dart File
class dataListing extends StatefulWidget {
const dataListing({Key? key}) : super(key: key);
#override
State<dataListing> createState() => _dataListingState();
}
class _dataListingState extends State<dataListing> {
#override
Widget build(BuildContext context) {
return Container();
}
}
class listingData{
String? ListingID, listingName, listingDescription, address, suburbName, phoneNumber, openingHours, Email, Website;
listingData({
this.ListingID,
this.listingName,
this.listingDescription,
this.address,
this.suburbName,
this.phoneNumber,
this.openingHours,
this.Email,
this.Website,
});
//constructor
List<listingData> datalist = [];
factory listingData.fromJSON(Map<String, dynamic> json){
return listingData(
ListingID: json["ListingID"],
listingName: json["listingName"],
listingDescription: json["listingDescription"],
address: json["address"],
suburbName: json["suburbName"],
phoneNumber: json["phoneNumber"],
openingHours: json["openingHours"],
Email: json["Email"],
Website: json["Website"],
);
}
}
Directory.dart file
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:app/pages/data.dart';
class directoryPage extends StatefulWidget {
#override
State<directoryPage> createState() => _directoryPageState();
}
class _directoryPageState extends State<directoryPage> {
// List serviceListing = [];
//
// getAllListing()async{
// String url = "URL HERE";
// var response = await http.get(Uri.parse(url));
// if (response.statusCode == 200){
// setState (() {
// serviceListing = json.decode(response.body);
// });
// print (serviceListing);
// return serviceListing;
// }
// }
bool error = false, dataloaded = false;
var data;
String dataurl = "URL HERE";
#override
void initState (){
loaddata();
super.initState();
// getAllListing();
}
void loaddata() {
Future.delayed(Duration.zero,() async {
var res = await http.post(Uri.parse(dataurl));
if (res.statusCode == 200) {
setState(() {
data = json.decode(res.body);
dataloaded = true;
});
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Directory'),
centerTitle: true,
elevation: 0,
backgroundColor: Color(0xFFA30B32),
//WSU Appbar Icon
leading: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset("assets/wsulogo.png", scale: 8.0),
),
),
body: Container(
padding: EdgeInsets.all(15),
child:dataloaded?datalist():
Center(
child:CircularProgressIndicator()
),
)
);
}
Widget datalist(){
if(data["error"]) {
return Text(data["errmsg"]);
}else{
List<listingData> datalist = List<listingData>.from(data["data"].map((i){
return listingData.fromJSON(i);
})
);
return Table( //if data is loaded then show table
border: TableBorder.all(width:1, color:Colors.black45),
children: datalist.map((listingdata){
return TableRow( //return table row in every loop
children: [
//table cells inside table row
TableCell(child: Padding(
padding: EdgeInsets.all(5),
child:Text(listingdata.ListingID!)
)
),
TableCell(child: Padding(
padding: EdgeInsets.all(5),
child:Text(listingdata.listingName!)
)
),
TableCell(child: Padding(
padding: EdgeInsets.all(5),
child:Text(listingdata.listingDescription!)
)
),
TableCell(child: Padding(
padding: EdgeInsets.all(5),
child:Text(listingdata.address!)
)
),
]
);
}).toList(),
);
}
}
}
Looks like the issue was actually unrelated to the dart side of things, the php code wasn't properly structuring the data. Cannot have underscores or spaces.
Correct-> $json["dballlisting"] = array (); (I renamed it to just "data" later)
Incorrect->$json["db_all_listing"] = array ();
The error seems to be originating from this line, the data['data'] is null which is expected to be an Array.
List<listingData> datalist = List<listingData>.from(data["data"].map((i){
return listingData.fromJSON(i);
})
You need to investigate your API call to make sure why it is happening. If the null value is expected then you need to add safeguards in your code to make sure it won't break when it encounter such scenarios. You can add null safety checks for that one way to do it would be to
List<listingData> datalist = List<listingData>.from((data["data"] ?? []).map((i){
return listingData.fromJSON(i);
})

Display and edit text into TextFormField using voice (Flutter Speech to text)

I am working on Flutter speech to text. The scenery is user can give their comment using voice. While they give input for comment by their voice they may edit the comment field and enter some text(given by their voice) into any position. Like, I give input using my voice and want to enter some words on the first or middle or any place where I think I've to add some words for completing my comments.
I am using speech_to_text: ^5.2.0. Following are the code sample. Here, I just came to display the text into TextFormField. The value remove when I re-enter my voice. But what I need the value have to be in TextFormField and I can edit it any position of the given word that I think I've to input here.
class MyApp extends StatefulWidget {
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String text = 'Hi';
bool isListening = false;
final _textEditingController = TextEditingController();
late stt.SpeechToText _speech;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
TextFormField(
controller: _textEditingController,
),
Text(text),
],
)
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: AvatarGlow(
animate: isListening,
endRadius: 150,
glowColor: Theme.of(context).primaryColor,
child: FloatingActionButton(
onPressed: toggleRecording,
child: Icon(isLintening ? Icons.mic : Icons.mic_none),
),
),
),
));
}
Future toggleRecording() => SpechApi.toggleRecording(
onResult: (text) => setState(() {
this.text = text;
_textEditingController.text = text;
}),
onListening: (isLintening) {
setState(() => this.isListening = isListening);
if(!isListening) {
Future.delayed(Duration(seconds: 1), () {
// Utils.scanText(text);
_textEditingController.text = text;
});
}
});
void onListen() async {
bool available = await _speech.initialize(
onStatus: (val) => print('onStatus: $val'),
onError: (val) => print('onError: $val'));
if (!isListening) {
if (available) {
setState(() {
isLintening = false;
_speech.listen(
onResult: (val) => setState(() {
_textEditingController.text = text;
}),
);
});
}
} else {
setState(() {
isLintening = false;
_speech.stop();
});
}
}
}

Load more option in flutter ListView

I want to fetch all the infinite list view data in parts, means Initially it load 10 data item and on scroll more it should fetch next 10 items.
I am fetching data from my Laravel api and in my Laravel api endpoint there is not option for per_page, so Please help me to integrate load more option of list view data.
Here is my List data.
List<Category> _categoryList = List<Category>();
CategoryService _categoryService = CategoryService();
bool isLoading = true;
#override
void initState() {
super.initState();
_getAllCategories();
}
_getAllCategories() async {
var categories = await _categoryService.getCategories();
var result = json.decode(categories.body);
result['data'].forEach((data) {
var model = Category();
model.id = data["id"];
model.name = data["categoryName"];
model.icon = data["categoryIcon"];
setState(() {
_categoryList.add(model);
isLoading = false;
});
});
}
And I am fetching all data in simple ListTile.
child: ListView.builder(
itemCount: //_categoryList.length,
itemBuilder: (context, index) {
return ListTile(
title: _categoryList.name
);
},
),
So I have a trick and I am using it in my project. What we need here is to load more data when we are at the end of the list. So to do that we can use the ListView.builder() only:
child: ListView.builder(
itemCount: _categoryList.length + 1,
itemBuilder: (context, index) {
if(index == _categoryList.length){
// loadMore();
// return Loading();
}
return ListTile(
title: _categoryList.name
);
}),
So what we are doing is that we have set _categoryList.length + 1 to the itemCount. If _categoryList.length was 10 then we will have 11 items in the ListView and the index range will be 0 - 10. So inside the builder, we are checking that the index is equals to _categoryList.length which is 10. If the index is equals to the length of _categoryList.length, then we are at the end of the List and we can simply call some functions to load more data from Api or to show a loading widget.
I guess I got your question right, in this way you can simply lazy load data when user gets to the end of the List without using any third party libraries.
This process called pagination. Laravel provides a function for it check Pagination in Laravel
For example
$users = DB::table('users')->paginate(15);// 15 is limit per page
And check it too Paging lib in flutter dev.
I have created a sample to load more data using web service
You can see this example and you can implement for you json data.
https://android-pratap.blogspot.com/2018/12/flutter-infinite-listview-using.html
import 'package:akeepo/randomuser_infinitelist.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: InfiniteUsersList(),
);
}
}
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class InfiniteUsersList extends StatefulWidget {
static String tag = 'users-page';
#override
State<StatefulWidget> createState() {
return new _InfiniteUsersListState();
}
}
class _InfiniteUsersListState extends State<InfiniteUsersList> {
List<User> users = new List<User>();
ScrollController _scrollController = new ScrollController();
bool isPerformingRequest = false;
int pageNumber = 0;
#override
void initState() {
super.initState();
// Loading initial data or first request to get the data
_getMoreData();
// Loading data after scroll reaches end of the list
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
_getMoreData();
}
});
}
// to show progressbar while loading data in background
Widget _buildProgressIndicator() {
return new Padding(
padding: const EdgeInsets.all(8.0),
child: new Center(
child: new Opacity(
opacity: isPerformingRequest ? 1.0 : 0.0,
child: new CircularProgressIndicator(),
),
),
);
}
#override
void dispose() {
_scrollController.dispose();
super.dispose();
}
// Webservice request to load 20 users data using paging
Future<List<User>> _getUsers() async {
List<User> users = new List<User>();
setState(() {
pageNumber++;
});
String url =
"https://api.randomuser.me/?page=$pageNumber&results=20&seed=abc";
print(url);
var response = await http.get(url);
var jsonData = json.decode(response.body);
print(jsonData);
var usersData = jsonData["results"];
for (var user in usersData) {
User newUser = User(user["name"]["first"] + user["name"]["last"],
user["email"], user["picture"]["large"], user["phone"]);
users.add(newUser);
}
return users;
}
_getMoreData() async {
if (!isPerformingRequest) {
setState(() {
isPerformingRequest = true;
});
List<User> newEntries = await _getUsers(); //returns empty list
if (newEntries.isEmpty) {
double edge = 50.0;
double offsetFromBottom = _scrollController.position.maxScrollExtent -
_scrollController.position.pixels;
if (offsetFromBottom < edge) {
_scrollController.animateTo(
_scrollController.offset - (edge - offsetFromBottom),
duration: new Duration(milliseconds: 500),
curve: Curves.easeOut);
}
}
setState(() {
users.addAll(newEntries);
isPerformingRequest = false;
});
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Users',
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.bold))),
body: Container(
child: ListView.builder(
shrinkWrap: true,
controller: _scrollController,
itemCount: users.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index == users.length) {
return _buildProgressIndicator();
} else {
return ListTile(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
UserDetailPage(users[index])));
},
title: Text(users[index].fullName),
subtitle: Text(users[index].mobileNumber),
leading: CircleAvatar(
backgroundImage: NetworkImage(users[index].imageUrl)),
);
}
})),
);
}
}
class User {
final String fullName;
final String email;
final String imageUrl;
final String mobileNumber;
User(this.fullName, this.email, this.imageUrl, this.mobileNumber);
}
// User Detail Page
class UserDetailPage extends StatelessWidget {
final User user;
UserDetailPage(this.user);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("User Details"),
),
body: Center(
child: Text(
user.fullName,
style: TextStyle(fontSize: 35.0),
),
),
);
}
}

Firebase Basic Query for datetime Flutter

I am trying to write a program to check if the time selected by the user already exists in the firebase firestore or not. If it does then I navigate back to the page where they select time again.
But as of now, I am succeeded in sending the date and time to firebase and but not the latter part.
DateTime _eventDate;
bool processing;
String _time;
bool conditionsStatisfied ;
#override
void initState() {
super.initState();
_eventDate = DateTime.now();
processing = false ;
}
inside showDatePicker()
setState(() {
print('inside the setState of listTile');
_eventDate = picked ;
});
inside the button (SAVE):
onPressed: () async {
if (_eventDate != null) {
final QuerySnapshot result = await FirebaseFirestore
.instance
.collection('events')
.where('event_date', isEqualTo: this._eventDate)
.where('selected_time', isEqualTo: this._time)
.get();
final List <DocumentSnapshot> document = result.docs;
if (document.length > 0) {
setState(() {
print('inside the method matching conditions');
showAlertDialogue(context);
});
}else{
final data = {
// "title": _title.text,
'selected_time ': this._time,
"event_date": this._eventDate
};
if (widget.note != null) {
await eventDBS.updateData(widget.note.id, data);
} else {
await eventDBS.create(data);
}
Navigator.pop(context);
setState(() {
processing = false;
});
}
};
some guidance needed on how do I resolve this issue!
Also, because of the else statement now the program won't write the date into firestore.
After Alot of research, I came to realize that if you send the data from calendar in DateTime format then, because of the timestamp at the end of the Date it becomes impossible to match to dates. Hence I formatted the DateTime value into (DD/MM/YYYY).
Here is the rest of the code for reference:
class _AddEventPageState extends State<AddEventPage> {
String _eventDate;
bool processing;
String _time;
#override
void initState() {
super.initState();
// _eventDate = DateTime.now();
processing = false ;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Please select a date'),),
body: Column(
children: [
hourMinute30Interval(),
Text('$_time'),
ListView(
scrollDirection: Axis.vertical,
shrinkWrap: true,
children: <Widget>[
ListTile(
title: Text(
'$_eventDate'),
onTap: () async {
DateTime picked = await showDatePicker(context: context,
initialDate: DateTime.now(),
firstDate: DateTime(DateTime.now().year - 1),
lastDate: DateTime(DateTime.now().year + 10),);
if (picked != null) {
setState(() {
print('inside the setState of listTile');
_eventDate = DateFormat('dd/MM/yyyy').format(picked) ;
});
}
},
),
SizedBox(height: 10.0),
ListTile(
title: Center(
child: Text('Select time for appointment!', style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
),
),
processing
? Center(child: CircularProgressIndicator())
: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(30.0),
color: Theme
.of(context)
.primaryColor,
child:MaterialButton(
child: Text('SAVE', style: TextStyle(
fontSize: 20,
color: Colors.white,
fontWeight: FontWeight.bold,
)),
onPressed: () async {
if (_eventDate != null) {
AddingEventsUsingRajeshMethod().getAvailableSlots(
_eventDate, _time).then((QuerySnapshot docs) async {
if (docs.docs.length == 1) {
showAlertDialogue(context);
}
else{
final data = {
// "title": _title.text,
'selected_time': this._time,
"event_date": _eventDate,
};
if (widget.note != null) {
await eventDBS.updateData(widget.note.id, data);
} else {
await eventDBS.create(data);
}
Navigator.pop(context);
setState(() {
processing = false;
});
}
});
}
}
),
),
),
],
),
],
),
);
}
showAlertDialogue method :
showAlertDialogue(BuildContext context) {
Widget okButton = FlatButton(onPressed: (){
Timer(Duration(milliseconds: 500), () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => datePicker()),
);
});
}, child: Text(' OK! '));
AlertDialog alert = AlertDialog(
title: Text('Slot unavailable'),
content: Text('This slot is already booked please select another slot'),
actions: [
okButton,
],
);
showDialog(context: context ,
builder: (BuildContext context){
return alert ;
}
);
}
The hourMinute30Interval() is nothing but a Widget that returns a timePickerSpinner which is a custom Widget. Tap here for that.
The Query that is run after passing the _eventDate and _time is in another class, and it goes as follows :
class AddingEventsUsingRajeshMethod {
getAvailableSlots(String _eventDate , String _time){
return FirebaseFirestore.instance
.collection('events')
.where('event_date', isEqualTo: _eventDate )
.where('selected_time', isEqualTo: _time)
.get();
}
}
You can name it something prettier ;)

Update flutter card data one by one

I'm experimenting with flutter, creating a small screen to fetch cryptocurrency data. I have three crypto name (BTC, ETH, LTC), each will be displayed on card, the rate on USD.
I can get the data for each currency, and display it. But in my code, if each data fetch took 1 second, the cards display will be updated after 3 seconds. All data will be fetched first, then screen updated using setState().
This is the initial working code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'coin_data.dart' as coinData;
class PriceScreen extends StatefulWidget {
#override
_PriceScreenState createState() => _PriceScreenState();
}
class _PriceScreenState extends State<PriceScreen> {
String _selectedCurrency = "USD";
List<coinData.CoinData> _coinData = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Coin Ticker'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildCoinCards(),
],
),
);
}
Card buildCoinCard(coinData.CoinData currentCoinData) {
return Card(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 28.0),
child: Text(
'1 ${currentCoinData.coinName()} = ${currentCoinData.last} $_selectedCurrency',
),
),
);
}
buildCoinCards() {
List<Card> coinCards = [];
for (var currentCoinData in _coinData) {
coinCards.add(
buildCoinCard(currentCoinData),
);
}
return Column(
children: coinCards,
);
}
#override
void initState() {
super.initState();
for (String crypto in coinData.cryptoList) {
_coinData.add(
coinData.CoinData(
last: 0,
displaySymbol: "$crypto-$_selectedCurrency",
),
);
}
updateCoinData();
}
void updateCoinData() async {
var coinDataFetch =
await coinData.CoinData().getAllCoinData(_selectedCurrency);
setState(() {
_coinData = coinDataFetch;
});
}
}
I'd like to update each item everytime a HTTP call is success. So the card will be updated one by one (took 1 second each) instead of waiting for 3 seconds. So I change the updateCoinData() to this, but it's not working.
void updateCoinData() async {
for (coinData.CoinData currentCoinData in _coinData) {
var fetchCoinData = await currentCoinData.getCoinData(
currentCoinData.coinName(), _selectedCurrency);
setState(() {
currentCoinData = fetchCoinData;
print(
currentCoinData.coinName() + " " + currentCoinData.last.toString());
});
}
}
I suppose I cannot update the List item on setState()?
How do I achieve this update one-by-one?
Thanks

Categories

Resources