Fetch Data from an API and save in an sqlite database Flutter Dart Android - flutter

I have a insertUser method that works fine when i click a button or trigger it another way. I have a fetchUser method that fetches users data from an API. I call the fetch method in initState to fetch the data as soon as the app launches and that is also working fine. In my fetchUser method, i loop through the data collected, pass it to a user object and save in a database. I am able to create user objects for each user but cant save it in the database. Here is my code.
Future<List<User>> fetchUser() async {
final response =
await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));
if (response.statusCode == 200) {
final parsed = json.decode(response.body).cast<Map<String, dynamic>>();
parsed.forEach((entry) {
String name = entry["name"];
String username = entry["username"];
String passcode = entry["username"];
print("id: $name, username: $username, passcode: $passcode");
var newUser = User(
name: name,
username: username,
passcode: name,
);
print(newUser.passcode);
UserDatabase.instance.insertUser(user); //this is not working
});
return parsed.map<User>((json) => User.fromMapp(json)).toList();
// return parsed.map<User>((json) => User.fromMap(json)).toList();
} else {
throw Exception('Failed to load users');
}
}
The insert method
insertUser(User user) async{
Database db = await instance.database;
return await db.insert(_table_field_agents, user.toUserMap(),conflictAlgorithm: ConflictAlgorithm.ignore
);
}
I call fetchUser in initState, everything works alright except saving the data to the database.

Related

How to fetch data and update it from firebase

I am having trouble trying to fetch data from firebase and updating the values from it.
I have a restaurant name and the number of times it has been picked (user chooses to go to that restaurant to eat). I am trying to retrieve the numPicked and update it by adding one if the user decides to go there again.
Here i am trying to fetch ONE specific document and trying to store the docID and the variables I need to update.
docID = doc.id; docID is return NULL
meaning that the foreach loop isn't even being read.
Future<bool> searchQuery(
{required String restaurantName,
required var userID,
required db}) async {
int addOne = 1; //addes one if it has been picked
//this is not working
try {
Query query2 =
db.where('userId', isEqualTo: FirebaseAuth.instance.currentUser!.uid);
Query query = query2.where('restaurantName', isEqualTo: restaurantName);
await query.get().then((querySnapshot) {
// ignore: avoid_function_literals_in_foreach_calls
querySnapshot.docs.forEach((doc) {
docID = doc.id;
numPicked = doc['numPicked'];
restaurantExist = true;
});
}).catchError((error) {
// print('error querying: #error');
});
} catch (ex) {
// ignore: avoid_print
print(ex);
}
//this is not working
int totalPicked = numPicked + addOne;
//if the restaurant exist then update the numpicked for that specific restaurant
if (restaurantExist) {
try {
var query = db
//.collection('NumRestaurantPicked')
.doc(docID);
await query.update({'numPicked': totalPicked.toString()});
} catch (ex) {}
}
return restaurantExist;
}
The docID and numPicked variables are not defined in the method signature, so they are not accessible outside of the try block. They should be defined as class variables, so they can be accessed from other methods.

updateDisplayName() not working after running createUserWithEmailAndPassword

I have a future method in a AuthService class to create new users with the inbuilt function createUserWithEmailAndPassword, but right after that I am trying to update the display name of that User? user but this never updates.
Future regEmailPass(String email, String password, String? username) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
User? user = result.user;
await user?.updateDisplayName(username);
UserInApp? userInApp = _userFromFireBaseUser(user);
await DatabaseService(user: userInApp).firstTimeCreateDB(username!);
return userInApp;
} catch (e) {
print(e.toString());
return null;
}
}
I even tried using the await user.reload() or double checking if my user was null in the first place, but in every situation, the displayName was set to null in the firestore database.

Unable to use a Future value - Flutter/Dart

I've fetched a json object and deserialized it and then returned it too.
I want to use this in another file.
I'm unable to assign the values that I'm getting in the first step.
Here are all the codes...
Service
Future getGeoPoints(String accessToken, String tripId) async {
String requestUrl;
var response = await get(
Uri.parse(requestUrl),
headers: {
'Authorization': "Bearer $accessToken",
},
);
if (response.statusCode == 200) {
Map<String, dynamic> responseBody = json.decode(response.body);
GetGeoPoints geoPoints = GetGeoPoints.fromJson(responseBody);
List listOfGeoPoints = [];
for (var geoPoint in geoPoints.geoPoints) {
listOfGeoPoints.add(
{
'latitude': geoPoint.latitude,
'longitude': geoPoint.longitude,
'timestamp': geoPoint.timeStamp,
},
);
}
// print('List of geo points: ' + '$listOfGeoPoints');
return listOfGeoPoints;
} else {
throw Exception('Failed to load data from server');
}
}
File where I need the above values
List routeCoordinates;
Future<void> getValues() async {
getGeoPoints(widget.accessToken, widget.tripId)
.then((value) => routeCoordinates = value);
}
When I run the app, routeCoordinates is null but when I hotreload, it contains the value.
I want to have the values as soon as the screen starts. What is the right way to assign the values here?
I've also tried this:
routeCoordinates = getGeoPoints...
It throws error..
Please help.. Thanks..
The function getGeoPoints() is an asynchronous one. But on the other file, you are not using the await keyword, instead you are using then(). So your code is not waiting for that function to return value.
Try using below code,
List routeCoordinates;
Future<void> getValues() async {
routeCoordinates = await getGeoPoints(widget.accessToken, widget.tripId);
}
Let us know how it went.
You need to use a FutureBuilder to define a behaviour depending on the state of the request. You'll be able to tell the widget what to return while your app is waiting for the response to your request. You can also return a specific widget if you get an error(if your user is offline, for example).
Edit: I've linked the official docs but give this article a read if it's not clear enough.

How do I print a value from an instance of 'User' in a flutter?

class User {
String token;
User({this.token});
}
class AuthService {
final String url = 'https://reqres.in/api/login';
final controller = StreamController<User>();
Future<User> signIn(String email, String password) async {
final response =
await post(url, body: {'email': email, 'password': password});
final data = jsonDecode(response.body);
final user = _userFromDatabaseUser(data);
// print(user.token);
controller.add(user);
return user;
}
//create user obj based on the database user
User _userFromDatabaseUser(Map user) {
return user != null ? User(token: user['token']) : null;
}
//user stream for provider
Stream<User> get user {
return controller.stream;
}
}
//in Sign in page
onPressed: () async {
if (_formKey.currentState.validate()) {
dynamic result = await _auth.signIn(email, password);
print(result); // Instance of 'User'
}
}
I am new to flutter and want to make an app that only authenticated users. I'm trying to read user token data from a stream. then check that token is not null if I got token then goto home page otherwise it will show error how do I print or store token value?
You can do is when you get the user after the sign In:
User result = await _auth.signIn(email, password);
Then to see the data you can do is
print(result.token);
which will give you the token, and then you can use the shared prefrences to store your token and access it.
Check out the docs for the it: https://pub.dev/packages/shared_preferences
You can override Object.toString method.
you can add this method in your User class to print the token instead of Instance of 'User'.
#override
String toString() {
// TODO: change the below return to your desired string
return "token: $token";
}
You can print using
print(userModel.toString());

How do I return to the user stream in flutter

I'm having an issue return a Stream to a StreamBuilder widget in a flutter. I'm trying to access a custom class that is stored token.
class User {
String token;
User({this.token});
}
===============================
class AuthService {
String url = 'https://reqres.in/api/login';
String token = '';
// {
// "email": "eve.holt#reqres.in",
// "password": "cityslicka"
// }
Map data;
Future signIn(String email, String password) async {
final response =
await post(url, body: {'email': email, 'password': password});
data = jsonDecode(response.body);
print(data['token']);
token = data['token'];
_userFromDatabaseUser(data);
return data;
}
//create user obj based on the database user
User _userFromDatabaseUser(Map user) {
return user != null ? User(token: user['token']) : null;
}
//user stream for provider
Stream<User> get user {
return .................. ;
}
You could use a stream controller:
class AuthService {
final String url = 'https://reqres.in/api/login';
final controller = StreamController<User>();
Future<User> signIn(String email, String password) async {
final response = await post(url, body: {'email': email, 'password': password});
final data = jsonDecode(response.body);
final user = _userFromDatabaseUser(data);
controller.add(user);
return user;
}
//create user obj based on the database user
User _userFromDatabaseUser(Map user) {
return user != null ? User(token: user['token']) : null;
}
//user stream for provider
Stream<User> get user {
return controller.stream;
}
Please note that this approach is a simplistic example that has some flaws, you should read up on it in the documentation.
If you use this for the purpose you describe, you may want to look into the bloc pattern and it's implementation as flutter-bloc. It might seem easier to do the user in this way by hand, but once you reach the point where you have multiple of those streams, you may want a more structured approach.
You can use
Stream<User> get user async*{
yield .................. ;
}
you can use yield keyword when you want to return stream object.
2nd way you can use a stream controller. You can add value in controller and
listen wherever you want to listen in your app there is no need to return stream