Flutter API Fetch and Sending Data from One screen to another screen - flutter

When I am logged in through the API I am getting the value User_id which I am able to print on console, but I want to use it on another screen.
So how can I send the data to another screen?
// First Screen
Future postMethod() async {
var api = Uri.parse("https://demo.likemyfiles.com/DS/api/auth/otp");
Map mapeddate = {
'phone': _phone.text,
'otp': _otp.text,
};
final response = await http.post(api, body: mapeddate);
print(response.body);
var res = json.decode(response.body);
print(res['user_id']);
Navigator.pushNamed(context, StartActivity.id); //here i want to send the User_Id
}
//Second Screen (Start Activity) in this screen there is a function FetchData where i want to use the data
Future fetchdata() async {
var url = await http.get(Uri.parse(
"http://demo.likemyfiles.com/DS/api/api_supervisor/supervisor/3")); //Instead of 3 i want
to use the User_Id variable
}

You should try to declare constructor the first page accept the id and push this id to second page or screen like this below code is first page
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ABC.withId(
id,
),
),
)
the create constructor inside second page screen
class ABC extends StatefulWidget {
#override
_ABCState createState() => _ABCState();
var id;
ABC.withId(String uid) {
id = uid;
}
}
accept your id inside widget using widget.id

Related

Added data is only showing after reloading in flutter

here is a popup screen to add the transaction to the app, as you can see here
and when the add button pressed the data will add to database and also to the dislpay , here is the code
ElevatedButton(
//on pressed
onPressed: () async {
final _categoryName = _nameEditingController.text;
if (_categoryName.isEmpty) {
return;
}
final _type = selectedCategoryNotifier.value;
//sending the data to model class
final _category = CategoryModel(
id: DateTime.fromMillisecondsSinceEpoch.toString(),
name: _categoryName,
type: _type,
);
//inserting the data to database
await CategoryDb.instance.insertCategory(_category);
//refreshing the ui
await CategoryDb.instance.refreshUI();
//and quitting the popup screen
Navigator.of(ctx).pop();
},
child: const Text('Add'),
),
and in this code you can see that I called 2 functions that for insert data and also refresh the UI, in the refresh UI function I added the function that to get all data from database to screen, here the code of all functions for CRUD operatins
const databaseName = 'category-database';
abstract class CategoryDbFunctions {
Future<List<CategoryModel>> getCategories();
Future<void> insertCategory(CategoryModel value);
}
//CRUD operations code
class CategoryDb implements CategoryDbFunctions {
CategoryDb._internal();
static CategoryDb instance = CategoryDb._internal();
factory CategoryDb() {
return instance;
}
ValueNotifier<List<CategoryModel>> incomeCategoryListListener =
ValueNotifier([]);
ValueNotifier<List<CategoryModel>> expenseCategoryListListener =
ValueNotifier([]);
#override
Future<void> insertCategory(CategoryModel value) async {
final _categoryDB = await Hive.openBox<CategoryModel>(databaseName);
await _categoryDB.add(value);
await refreshUI();
}
#override
Future<List<CategoryModel>> getCategories() async {
final _categoryDB = await Hive.openBox<CategoryModel>(databaseName);
return _categoryDB.values.toList();
}
Future<void> refreshUI() async {
final _allCategories = await getCategories();
incomeCategoryListListener.value.clear();
expenseCategoryListListener.value.clear();
await Future.forEach(
_allCategories,
(CategoryModel category) {
if (category.type == CategoryType.income) {
incomeCategoryListListener.value.add(category);
} else {
expenseCategoryListListener.value.add(category);
}
},
);
}
}
so I checked the all things , but I couldn't find where I'm missing parts,
and here is the main part, it is adding to the database also displaying after I refresh the UI or change the tab here you can see what I mean by 'changing the tab'
this is the problem I'm trying to fix this for 2 day, i couldn't find any solution or mistake in my code
There many ways you can handle this problem.
but I dont see where you notify youre ui that the data has been changed, flutter does only update the ui when you use setState etc.. these functions help flutter updating the ui where the data changed.
i would recommend you to use setState in the place you invoke youre dialog.
onTap:(){
setState(){
await dialogStuff();
}
}

Flutter Navigator pushnamed object not working when sent to class as parameter

I am trying to refactor my code and use a separate class object to register users and then send them to the correct page which is either the awaiting for email confirmation screen(if they haven't confirmed their email address) or the actual chat screen in the app.
I pass the Navigator.pushNamed object from the Flutter material build to the separate class object, but the Navigator.pushNamed doesn't work when it is sent as a parameter to the class object. It only worked when it is in the main build.
This is the main section that collects the parameters and sends them to the class
Widget build(BuildContext context) {...
Registration(
email: email,
password: password,
awaitingEmailConfPage:
() async {
await Navigator.pushNamed(context, EmailConfirmation.id);
},
confirmedEmailConfPage: () async {
await Navigator.pushNamed(context, ChatScreen.id);
}
).registerNewUser();
This is the class object that receives the Navigator.pushNamed but doesn't want to allow it to work and send users to the correct screen.
class Registration {
Registration(
{required this.awaitingEmailConfPage,
required this.confirmedEmailConfPage});
final _auth = FirebaseAuth.instance;
Future Function() awaitingEmailConfPage;
Future Function() confirmedEmailConfPage;
void registerNewUser() async {
try {
User? user = _auth.currentUser;
if (user!.emailVerified) {
await awaitingEmailConfPage;
} else {
await confirmedEmailConfPage;
}
}
}
If you want to call a function that receive as parameter you need to use call() method:
if (user!.emailVerified) {
await awaitingEmailConfPage.call();
} else {
await confirmedEmailConfPage.call();
}

Instance of 'Future<dynamic>' Flutter

I am trying to pass the Json data to the next screen after login.
Get Instance of 'Future' Flutter is displaying in print statement
onPressed()
var Data = getData(Username,Password);
print(Data);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ActivePage(jsondata:Data);
},
));
getData() print the exact json response
getData(username,password) async {
Auth auth = Auth();
var Data = await auth.signup(username, password);
print(Data);
}
Change your getData method to given code below:
getData(username,password) async {
Auth auth = Auth();
var Data = await auth.signup(username, password);
print(Data);
return Data;
}
As I can see, looks like you forget to return Data from getData method.

Flutter: Refresh image after add

If I have added data to the flutter in firebase, but I want to add more, the image on the added page still appears before the image, how do I refresh it to return to blank as before?
DateTime now = DateTime.now();
String format = DateFormat('dd:mm:yy').format(now);
var fullImageName = 'foto-$format' + '.jpg';
var fullImageName2 = 'foto-$format' + '.jpg';
final StorageReference ref =
FirebaseStorage.instance.ref().child(fullImageName);
final StorageUploadTask task = ref.putFile(image);
// Wait upload task to complete
final StorageTaskSnapshot downloadUrl =
(await task.onComplete);
// Get image uRL
final String url = (await downloadUrl.ref.getDownloadURL());
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
DocumentReference ref = await db
.collection('resep')
.add({'nama': '$nama', 'resep': '$resep', 'image': '$url', 'email' : widget.email});
setState(() => id = ref.documentID);
Navigator.of(context).pop();
}
Let Say above code you have written is in Page2 which is navigated from Page1.
So when you upload the image on firebase storage and pop the page2. Then you can refresh the page as following,
When you push a new page2 from page1 you can have its pop callback.
// To check if you got your callback or not just pass bool data type with MaterialPageRoute
Navigator.push(context, MaterialPageRoute<bool>(builder: (context) => page2()),).then((bool res) {
// check here if you got your callback data or not
if(res!=null && res==true){
// fetch your updated content here
}
});
When you pop your page2 then,
Navigator.of(context).pop(true);

new to flutter. I'm want to go to a webapi based on url passed not hard code path

I'm working with web API's and need to pass in a api url that I retrieved to fetch some data then display the data. I am able to create a listview from a api url that's hard coded, but don't know how to send in a parameter to display info based on that selected url. How do send in the url fetch the data and display it
----------api_data_details.dart file---------
class PokemonRepository {
//want to pass in a url
final String url ;
PokemonRepository({this.url});
final JsonDecoder _decoder = new JsonDecoder();
Future<Pokemon> fetch() async{
final detailsresponse = await http.get(url);
final jsonBody = detailsresponse.body;
final statusCode = detailsresponse.statusCode;
if(statusCode < 200 || statusCode >= 300 || jsonBody == null) {
throw new FetchDataException("Error while getting pokemon details [StatusCode:$statusCode, Error:${detailsresponse.reasonPhrase}]");
}
final pokemonContainer = _decoder.convert(jsonBody);
final pokemonDetails = pokemonContainer['results'];
return pokemonDetails.map( (pokemondetails) =>
Pokemon.fromMap(pokemondetails)) ;
}
--------------api_data.dart file--------------
class Pokemon{
final int id;
final String name;
final int height;
final List<Moves> moves;
final String imageUrl;
final int weight;
const Pokemon({this.id,this.name,this.height, this.weight,this.imageUrl,this.moves});
Pokemon.fromMap(Map<String, dynamic> map):
id = map['id'],
name = map['name'],
height = map['height'],
imageUrl = map['sprites']['front-default'],
weight = map['weight'],
moves = <Moves>[
new Moves(name: map['name'])
];
}
class Moves {
final String name;
const Moves({this.name});
}
abstract class PokemonDetailRepository{
Future<Pokemon> fetch();
}
---------------pokemon_view.dart file----------------
class _PokemonListItem extends ListTile {
_PokemonListItem(PokemonList pokemonlist):
super(
title : Text(pokemonlist.name),
subtitle: InkWell(
child: Text(pokemonlist.url, style: TextStyle(fontSize: 8.0),),
onTap: (){
//want to click on url and pass it to the PokemonRepository class to retrieve the new data and then open a new page with the details from the new request
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => PokemonDetailPage( pokemonlist.url,),
}
)
);
Can't you just pass the url in to the fetch function as a parameter?
So the signature for fetch becomes:
Future<Pokemon> fetch(String url) {
// do stuff
}
If you want to pass a default value, the syntax is a little different:
Future<Pokemon> fetch({String url = "http://default"}) {
// do stuff
}
And then the caller can choose to pass a url or not.
Remember that Flutter is written in Dart, so ultimately you're just writing dart code. For language-related questions (like how to pass parameters to functions) the language tour is an excellent resource.