How to send json data from on route to another route - json

In my Flutter application, I am trying to pass JSON data from one route to another. The challenge I am facing is how to pass a list as a parameter. The first screen contains a list of JSON data that has been fetched, and I aim to show the complete details of each item when the user clicks on the respective ListTile.
you will find the onTap() in JsonParsingPodo.dart
here's my code :
posts.dart (plain old dart object file)
class PostList {
final List<Post> posts;
PostList({required this.posts});
factory PostList.fromJson(Map<String, dynamic> parsedJson) {
List<dynamic> postsJson = parsedJson['posts'] as List;
List<Post> posts = <Post>[];
posts = postsJson.map((e) => Post.fromJson(e)).toList();
return PostList(posts: posts);
}
}
class Post {
int userId;
int id;
String title;
String body;
Post(
{required this.id,
required this.body,
required this.title,
required this.userId});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'],
body: json['body'],
title: json['title'],
userId: json['userId']);
}
}
JsonParsingPodo.dart (First Screen)
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:podo_practice/posts.dart';
import 'display.dart';
class JsonParsingPodo extends StatefulWidget {
const JsonParsingPodo({super.key});
#override
State<JsonParsingPodo> createState() => _JsonParsingPodoState();
}
class _JsonParsingPodoState extends State<JsonParsingPodo> {
late Future<PostList> data;
#override
void initState() {
super.initState();
Network network = Network("https://dummyjson.com/posts");
data = network.loadPost();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text("PODO: json"),
),
body: Center(
// ignore: avoid_unnecessary_containers
child: Container(
child: FutureBuilder(
future: data,
builder: (context, AsyncSnapshot<PostList> snapshot) {
List<Post> allposts;
if (snapshot.hasData) {
allposts = snapshot.data!.posts;
return createListView(allposts, context);
}
return const CircularProgressIndicator();
}),
),
));
}
Widget createListView(List<Post> data, BuildContext context) {
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, int index) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Divider(
height: 5.0,
),
ListTile(
title: Text("${data[index].title}"),
subtitle: Text("${data[index].body}"),
leading: Column(
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.green,
radius: 23,
child: Text("${data[index].id}"),
),
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DisplayData()),
// *what to pass here??*
);
},
),
],
);
});
}
}
class Network {
final String url;
Network(this.url);
Future<PostList> loadPost() async {
final response = await get(Uri.parse(Uri.encodeFull(url)));
if (response.statusCode == 200) {
//ok
return PostList.fromJson(json.decode(response.body));
} else {
throw Exception("Failed to load data. ");
}
}
}
DisplayData.dart (Second Screen)
import 'package:flutter/material.dart';
import 'package:podo_practice/posts.dart';
class DisplayData extends StatefulWidget {
const DisplayData({super.key});
#override
State<DisplayData> createState() => _DisplayDataState();
}
class _DisplayDataState extends State<DisplayData> {
late Future<PostList> data;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text("Display Post"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: Column(
children: [
// Text(data);
],
),
),
),
);
}
}
I have recently started learning Flutter and don't have much knowledge. I tried reading articles on Stack Overflow about this thing, but I didn't understand much. So, I have decided to post a question for help. Please assist me in completing the following code.
On the "Display Data" page, I need to display the **title **and its **description **when the user clicks on the ListItem.

onListile tap send particular object using index
Widget createListView(List<Post> data, BuildContext context) {
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, int index) {
Post post = data[index]
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Divider(
height: 5.0,
),
ListTile(
title: Text("${data[index].title}"),
subtitle: Text("${data[index].body}"),
leading: Column(
children: <Widget>[
CircleAvatar(
backgroundColor: Colors.green,
radius: 23,
child: Text("${data[index].id}"),
),
],
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const DisplayData(post:post)),
// *what to pass here??*
);
},
),
],
);
});
}
}
get post on constructor to display
import 'package:flutter/material.dart';
import 'package:podo_practice/posts.dart';
class DisplayData extends StatefulWidget {
final Post post;
const DisplayData({super.key,required this.post});
#override
State<DisplayData> createState() => _DisplayDataState();
}
class _DisplayDataState extends State<DisplayData> {
late Future<PostList> data;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text("Display Post"),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: Column(
children: [
// Text(data);
],
),
),
),
);
}
}

Related

I am a flutter beginner while getting json data from internet it is not showing in my app.. Solve it

This is my complete code and i don't know what kind of error i have made
Correct it if you know, as i am beginner in flutter.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Mydata(),
);
}
}
class Mydata extends StatefulWidget {
const Mydata({super.key});
#override
State<Mydata> createState() => _MydataState();
}
class _MydataState extends State<Mydata> {
Future<List<String>> ebdetails() async {
var response =
await http.get(Uri.parse('http://117.247.181.113:8000/eb/1/'));
return jsonDecode(response.body);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 0,
centerTitle: true,
title: const Text(
'Json Datas',
style: TextStyle(
color: Colors.black,
),
),
backgroundColor: Colors.white,
),
body: Center(
child: FutureBuilder(
builder: (context, snapshot) {
if (snapshot.hasError) {
return const Center(
child: Text('Data Error'),
);
} else if (snapshot.hasData) {
return Center(
child: ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, i) {
return Text(
snapshot.data![i],
);
},
));
} else {
return const CircularProgressIndicator();
}
},
future: ebdetails(),
),
),
);
}
}
I am fetching data over local ip but it seems to have some sort of error i have made, but its hard for me to find..
It shows only "Data error which i have given in Futurebuilder..
[
{
"id": 1,
"R_Current": -1.0,
"Y_Current": -1.0,
"B_Current": -1.0,
"R_Voltage": 208,
"Y_Voltage": 235,
"B_Voltage": 208,
"UPS_Voltage": 100,
"UPS_Current": 143.0,
"UPS_Battery": 99
}
]
so according to your data it is not the list of the String change the return type of the method to this
Future<List<dynamic>> ebdetails() async {
var response =
await http.get(Uri.parse('http://117.247.181.113:8000/eb/1/'));
return jsonDecode(response.body);
}
Edit:
Ok so your problem was that you pass map to the Text() widget and the text widget needs string as a parameter so you have to convert the snapshot.data to string and then pass it to the Text widget.
snapshot.data.toString()
try to convert the response into a custom Dart object
see this
[1]: https://docs.flutter.dev/cookbook/networking/fetch-data
I have changed the code and got the answer i.e snapshot.data![i].toString()
builder: (context, snapshot) {
if (snapshot.hasData) {
return Center(
child: ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, i) {
return Text(
snapshot.data![i].toString(),
);

Error: type 'List<dynamic>' is not a subtype of type 'String'

I am new to flutter. I am trying to fetch the data from Firestore by Stream. But it is giving me error. I am trying to fetch a String and a List but I don't know what to change in code to fetch the List. In code, 'name' field is String and 'overview' field is a List.
import 'package:firebaseAuth/firebaseAuthDemo.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class FindDiseases extends StatefulWidget {
final User user;
const FindDiseases({Key key, this.user}) : super(key: key);
#override
_FindDiseasesState createState() => _FindDiseasesState();
}
class _FindDiseasesState extends State<FindDiseases> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
FirebaseAuth _auth = FirebaseAuth.instance;
List diseasesList = [];
dynamic data;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.teal,
//automaticallyImplyLeading: false,
title: Text(
"Diseases List",
),
),
key: _scaffoldKey,
body: Container(
color: Colors.white,
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection("diseases")
.orderBy('id')
.snapshots(),
builder: (context, snapshot) {
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
DocumentSnapshot user = snapshot.data.docs[index];
return Card(
color: Colors.white,
child: FlatButton(
onPressed: () {},
child: ListTile(
title: Text(user['name']),
subtitle: Text(user['overview']),
),
),
);
},
);
},
),
),
);
}
Data is something like as shown below:
"name": "Agoraphobia",
"overview": "[
'Losing weight.', 'Stopping medications or supplements.', 'Having surgery.'
]"
It is because you are using
subtitle: Text(user['overview']),
as a string while in data this data is in list format try to get index wise data from it then try to show as string
In your data "overview" is a type of list and you are trying to get it as string.
List<String> list = user['overview'];
String data = String.join(", ", list);
return Card(
color: Colors.white,
child: FlatButton(
onPressed: () {},
child: ListTile(
title: Text(user['name']),
subtitle: Text(data),
),
),
);

I have a response of json body from a login API . I made a model class for that json. Now how to use it in my pages to fetch data?

I have logged in from a api . Then i got a response of json . I can fetch data from login to homepage . For that i created a constructor in homepage and pass it in Login page where i made navigator for the homepage . But i know it's not good practice to fetch data like it. using model class is more smart way. I added my code here of login, homepage and model . Now my data can only communicate between these two page . But i need to fetch data to another pages too.
login.dart
import 'package:api_login/model/response_model.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../sharePreference.dart';
import 'homepage.dart';
class Login extends StatefulWidget {
UserDetails userDetails = new UserDetails();
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
var notification ;
bool isprocesscomplete = false;
TextEditingController _userController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
final _scaffoldKey = GlobalKey<ScaffoldState>();
String BaseUrl = "my url";
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
body: SingleChildScrollView(
child: Center(
child: Container(
height: 770,
color: Colors. lightBlue,
padding: EdgeInsets.fromLTRB(20, 100, 20, 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Login",
style: TextStyle(fontSize: 32),
),
SizedBox(
height: 30,
),
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Container(
height: 220,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(30),
child: TextField(
controller: _userController,
decoration: InputDecoration(hintText: "Username"),
),
),
Padding(
padding: const EdgeInsets.all(30),
child: TextField(
controller: _passwordController,
obscureText: true,
decoration: InputDecoration(hintText: "Password"),
),
),
],
),
),
),
SizedBox(
height: 60,
width: MediaQuery.of(context).size.width,
child: RaisedButton(
color: Colors.blue,
onPressed: () {
if (_userController.text == "" ||
_passwordController.text == "") {
final snackBar = SnackBar(
content: Text("Enter Username and Password"));
_scaffoldKey.currentState.showSnackBar(snackBar);
} else {
signIn(_userController.text, _passwordController.text);
}
},
child: ProgressButton(),
shape: RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(16),
),
),
),
SizedBox(
height: 20,
),
FlatButton(
child: Text("Forgot password"),
onPressed: () {},
),
],
),
),
),
),
);
}
Widget ProgressButton() {
if (isprocesscomplete != false) {
return CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white));
} else {
return new Text(
"Sign In",
style: const TextStyle(
color: Colors.white,
fontSize: 15.0,
),
);
}
}
void signIn(String username, String password) async {
setState(() {
isprocesscomplete = true;
});
var response = await http.post(BaseUrl,
headers: {"Content-Type": "application/json"},
body: json.encode({
"username": username,
"password": password,
}));
Map<String, dynamic> value = json.decode(response.body);
notification = value["notifications"];
// print('Response ${response.body}');
if (response.statusCode == 200) {
try {
///You don't need it but it will be cool for show progress dialgo for 4 second then redirect even if we get reslut
Future.delayed(Duration(seconds: 4), () {
// 5s over make it false
setState(() {
isprocesscomplete = true;
});
});
Map<String, dynamic> value = json.decode(response.body);
print('Response ${response.body}');
SharedPrefrence().setToken(value['api_token'].toString());
SharedPrefrence().setName(value['user_name']);
SharedPrefrence().setUserId(value['user_id'].toString());
///This is used when user loged in you can set this true,
///next time you open you need to check loginc in main.dart or splashscreen if this is true if it is true then
///redirect to home page it is false then redirect to Login page
///When you logout the app make sure you set this as false like "SharedPrefrence().setLoggedIn(false);"
SharedPrefrence().setLoggedIn(true);
///Redirect to Home page
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => HomePage(
user_name: value['user_name'],
api_token: value['api_token'],
notification: notification,
// payment: payment ,
)),
ModalRoute.withName("/login"));
} catch (e) {
e.toString();
final snackBar =
SnackBar(
content: Text("something wrong,Try again 😑"),
behavior: SnackBarBehavior.floating,
);
_scaffoldKey.currentState.showSnackBar(snackBar);
}
} else {
var message = value['error'];
final snackBar = SnackBar( backgroundColor: Colors.redAccent[700],
content: Text(message.toString()),
behavior: SnackBarBehavior.floating, );
_scaffoldKey.currentState.showSnackBar(snackBar);
}
}
}
homepage.dart
import 'package:api_login/model/response_model.dart';
import 'package:api_login/pages/details.dart';
import 'package:api_login/pages/settingPage.dart';
import 'package:api_login/widget/neumorphsm.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../sharePreference.dart';
import 'login.dart';
import 'login.dart';
class HomePage extends StatefulWidget {
final payment;
final count ;
String user_name;
final api_token;
final user_id ;
final payment_id;
final List<dynamic> notification ;
// List data ;
HomePage({ this.user_name, this.api_token , this.user_id, #required this.notification ,
this.count, this.payment, this.payment_id});
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String arrayLength ;
String nametoprint;
String tokentoprint;
#override
void initState() {
super.initState();
Future name = SharedPrefrence().getName();
name.then((data) async {
nametoprint = data;
print(nametoprint);
});
Future token= SharedPrefrence().getToken();
token.then((data) async {
tokentoprint= data;
print(tokentoprint);
});
}
int counter ;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Cash-Management"),
backgroundColor: Colors.blue,
actions: [
new Stack(
children: <Widget>[
new IconButton(icon: Icon(Icons.notifications), onPressed: () {
setState(() {
counter = 0;
});
}),
counter != 0 ? new Positioned(
right: 11,
top: 11,
child: new Container(
padding: EdgeInsets.all(2),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(6),
),
constraints: BoxConstraints(
minWidth: 14,
minHeight: 14,
),
child: Text(
" ${widget.notification.length} ",
style: TextStyle(
color: Colors.white,
fontSize: 8,
),
textAlign: TextAlign.center,
),
),
) : new Container()
],
),
IconButton(
icon: Icon(Icons.exit_to_app),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Login()),
);
}),
],
),
body: ListView(
children: <Widget>[
Card(
color: Colors.lightBlue,
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new SettingPage()));
},
child: Container(
height: 120,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Profile",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Text(
"Name:${widget.user_name}",
// " ${widget.username} ",
style: TextStyle(fontSize: 16),
),
// Text(
// " ${widget.notification.length} ",),
// Text(" ${nametoprint} "),
],
),
),
),
),
Container(
color: Colors.lightBlue,
height: 400,
child: ListView.builder(
itemCount: widget.notification == null ? 0 : widget.notification.length,
itemBuilder: (context, index){
final count = widget.notification ;
print(count.length);
return Card(
color: Colors.blue,
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new DetailPage()));
},
child: Column(
children:<Widget>[
Text('Amount'),
ListTile(
title: Text(widget.notification[index] ["data"]["amount"].toString()),
subtitle: Text(widget.notification[index]["data"]["message"].toString()),
) ,
Text('Created at '),
ListTile(
title: Text(widget.notification[index] ["created_at"].toString()),
),
Text('updated at'),
ListTile(
title: Text(widget.notification[index] ["updated_at"].toString()),
),
],
),
),
);
}),
),
Container(
color: Colors.blue,
height: 130,
child: Button()
),
],
),
// floatingActionButton: FloatingActionButton(onPressed: () {
// print("Increment Counter");
// setState(() {
// counter++;
// });
// }, child: Icon(Icons.add),),
),
);
}
}
response_model.dart
class UserDetails {
int userId;
String userName;
String apiToken;
List<Notifications> notifications;
UserDetails({this.userId, this.userName, this.apiToken, this.notifications});
UserDetails.fromJson(Map<String, dynamic> json) {
userId = json['user_id'];
userName = json['user_name'];
apiToken = json['api_token'];
if (json['notifications'] != null) {
notifications = new List<Notifications>();
json['notifications'].forEach((v) {
notifications.add(new Notifications.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['user_id'] = this.userId;
data['user_name'] = this.userName;
data['api_token'] = this.apiToken;
if (this.notifications != null) {
data['notifications'] =
this.notifications.map((v) => v.toJson()).toList();
}
return data;
}
}
class Notifications {
String id;
String type;
int notifiableId;
String notifiableType;
Data data;
Null readAt;
String createdAt;
String updatedAt;
Notifications(
{this.id,
this.type,
this.notifiableId,
this.notifiableType,
this.data,
this.readAt,
this.createdAt,
this.updatedAt});
Notifications.fromJson(Map<String, dynamic> json) {
id = json['id'];
type = json['type'];
notifiableId = json['notifiable_id'];
notifiableType = json['notifiable_type'];
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
readAt = json['read_at'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['type'] = this.type;
data['notifiable_id'] = this.notifiableId;
data['notifiable_type'] = this.notifiableType;
if (this.data != null) {
data['data'] = this.data.toJson();
}
data['read_at'] = this.readAt;
data['created_at'] = this.createdAt;
data['updated_at'] = this.updatedAt;
return data;
}
}
class Data {
int paymentId;
String generatePaymentId;
String message;
int amount;
Data({this.paymentId, this.generatePaymentId, this.message, this.amount});
Data.fromJson(Map<String, dynamic> json) {
paymentId = json['payment_id'];
generatePaymentId = json['generate_payment_id'];
message = json['message'];
amount = json['amount'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['payment_id'] = this.paymentId;
data['generate_payment_id'] = this.generatePaymentId;
data['message'] = this.message;
data['amount'] = this.amount;
return data;
}
}
It will be helpful if anyone let e know how to show detail page from this section.
ListView.builder(
itemCount: widget.notification == null ? 0 : widget.notification.length,
itemBuilder: (context, index){
final count = widget.notification ;
print(count.length);
return Card(
color: Colors.blue,
child: InkWell(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new DetailPage()));
},
You can use widget.user_name, widget.api_token in HomePage, and pass it to Details Page.
Home Page
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new DetailPage(userName :widget.user_name, apiToken: widget.api_token)));
If you want the data to be used globally in your application, perhaps you can fetch your data from API before MaterialApp() so that your data can be used globally.
Other way is you can pass your UserDetails() data to next page by calling them inside your Navigator.push(). You can read more detail example here

Flutter. Add a json.decode value to a String that can be used in the UI

Maybe this is a simple question, but I can't find the answer to it.
My app has 2 screens. 1st has a single button
onPressed: () {
fetchCurrentTitle();
Navigator.push(context,
MaterialPageRoute(builder: (context) => Screen2Widget()));
},
fetchCurrentTitle() method fetches data from json and decodes it.
I can see the return using:
final streamFullTitle = json.decode(response.body)['data'][0]['title'];
print(streamFullTitle);
I get the desired response of the current title in the console.
In the 2nd screen I have a hardcoded List. Where items have these values:
class List {
String id;
String streamer;
String logoUrl;
String title;
}
The first three attribute in List class dont need to change so they are hardcoded. I just need to assign the title value fromfetchCurrentTitle() to the String title. in class List.
Look of one of my list items
My fetchCurrentTitle() works as intended
Future<String> fetchCurrentTitle() async {
http.Response response = await http.get(...
I want the user to push the button on the first screen to go to the second screen and show a spinner with title "looking for title" and then get the new title instead of waiting fetchCurrentTitle() to complete only entering the second screen.
Thank you in advance.
You can try to run your fetchCurrentTitle() in the second screen on
void initState() {
super.initState();
fetchCurrentTitle()
/// show or set visibility for loading spinner
}
After you get the title value, you can simply assign new title by
List existingList = new List(id,streamer,logoUrl,title);
existingList.id = titleValueFromApi
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:sample_project_for_api/Employee.dart';
void main() => runApp(MaterialApp(
title: "App",
home: MyApp(),
));
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('home page'),
),
body: Center(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
child: RaisedButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => SecondScreen()));
},
child: const Text('First Page')),
)),
);
}
}
class SecondScreen extends StatefulWidget {
#override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
bool _isLoading = false;
Employee sampleData;
#override
void initState() {
super.initState();
getYouData();
}
Future<String> loadPersonFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
getYouData() async {
setState(() {
_isLoading = true;
});
String jsonString = await loadPersonFromAssets();
final data = employeeFromJson(jsonString);
sampleData = data;
// this is where you get the data from the network
Future.delayed(const Duration(seconds: 5), () {
// this is sample delay for you to know the delay.
// you can say this is loading your data
setState(() {
_isLoading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Container(
child: _isLoading
//here give your message getting the title
? CircularProgressIndicator()
: Card(
child: Column(
children: <Widget>[
Text('your 1st hardcoded text'),
Text('your 2st hardcoded text'),
Text('your 3st hardcoded text'),
Text(
'This is your dynamic data after fetching :${sampleData.employeeName}')
],
),
),
),
),
),
);
}
}
check out this example you will give you an idea of what to do
1) going from one page to another page
2) loading you data , while that showing the spinner
3) on fetching the data update the UI.
let me know about this.
Thanks.
Try this,
import 'dart:convert';
import "package:flutter/material.dart";
import 'package:http/http.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Page1(),
);
}
}
class Page1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page 1")),
body: Center(
child: RaisedButton(
child: Text("Goto Page2"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Page2(),
),
);
},
),
),
);
}
}
class Page2 extends StatefulWidget {
#override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2> {
Future<void> _initLoader;
String _title;
#override
void initState() {
_initLoader = _loadInitData();
super.initState();
}
Future<void> _loadInitData() async {
await Future.delayed(Duration(seconds: 2));
//_title = await fetchCurrentTitle();
_title = "This is the Loaded Title";
}
Future<String> fetchCurrentTitle() async {
Response response = await get("...");
return json.decode(response.body)['data'][0]['title'];
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Page 2")),
body: FutureBuilder(
future: _initLoader,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
CircularProgressIndicator(),
const SizedBox(height: 8.0),
Text("Looking for Title"),
],
),
);
else if (snapshot.hasError)
return Center(
child: Text("Error: ${snapshot.error}"),
);
else
return Center(
child: Text("$_title"),
);
},
),
);
}
}

Flutter: Loading json data within second page Flutter Class timing out without error

I've generated a listView from the Pokemon API of a list of Pokemon, I then have onTap events to trigger a new page/class, where I'm passing the name and URL from the API to the new secondPage Class/Screen.
I need to make a second request in this new page because the API Url needs to change to grab specific details but my request seems to be timing out..
Here is my code: If loaded into a new project the first screen should function fine, loading a bunch of Pokemon and their API specific URLs into a listView.
I can successfully pass the name and URL onto the second screen because they do appear in the Appbar.
However when loading the new json data it seems to be timing out without any error.
Does anyone have any advice for a newbie trying to get his footing?
import 'dart:async';
import 'dart:convert';
import 'package:basic_utils/basic_utils.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController editingController = TextEditingController();
String url = 'https://pokeapi.co/api/v2/pokemon/?limit=151';
List data;
Future<String> makeRequest() async {
var response = await http
.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
setState(() {
var extractData = json.decode(response.body);
data = extractData["results"];
});
}
#override
void initState() {
this.makeRequest();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Pokemon List'),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: new TextField(
onChanged: (value) {
},
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
contentPadding: const EdgeInsets.all(10.0),
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(6.0))
),
),
),
),
Expanded(
child: new ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return new ListTile(
title: new Text(StringUtils.capitalize(data[i]["name"])),
subtitle: new Text(data[i]["url"]),
// leading: new CircleAvatar(
// backgroundImage:
// new NetworkImage(data[i]["picture"]["thumbnail"]),
// ),
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) =>
new SecondPage(data[i])
)
);
},
);
}
),
),
],
),
),
);
}
}
// Class for getting Specific Details on SecondPage
class Post {
final String name;
final int weight;
Post({this.name, this.weight});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
name: json['name'],
weight: json['weight'],
);
}
}
// New Request for Specific Details
class SecondPage extends StatelessWidget {
SecondPage(this.data);
final data;
Future<Post> fetchPost() async {
final response =
await http.get('https://pokeapi.co/api/v2/pokemon/' + data["name"]);
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON.
return Post.fromJson(json.decode(response.body));
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
Future<Post> post;
#override
void initState() {
fetchPost();
post = fetchPost();
}
#override
Widget build(BuildContext context) =>
new Scaffold(
appBar: new AppBar(
title: new Text(data["name"] + ' - ' + data["url"])),
body: new Center(
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.all(30.0),
child: FutureBuilder<Post>(
future: post,
builder: (context, snapshot) {
if (snapshot.hasData) {
Text(snapshot.data.name);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
),
),
],
),
)
);
}
Man, I rewrite your code as I like
import 'dart:async';
import 'dart:convert';
//import 'package:basic_utils/basic_utils.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController editingController = TextEditingController();
String url = 'https://pokeapi.co/api/v2/pokemon/?limit=151';
List data;
Future<String> makeRequest() async {
var response = await http.get(Uri.encodeFull(url), headers: {"Accept": "application/json"});
setState(() {
var extractData = json.decode(response.body);
data = extractData["results"];
});
}
#override
void initState() {
super.initState();
makeRequest();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Pokemon List'),
),
body: Container(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(15.0),
child: TextField(
onChanged: (value) {},
decoration: InputDecoration(
labelText: "Search",
hintText: "Search",
contentPadding: const EdgeInsets.all(10.0),
prefixIcon: Icon(Icons.search),
border: OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(6.0))),
),
),
),
Expanded(
child: ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return ListTile(
title: Text(data[i]["name"].toString().toUpperCase()),
subtitle: Text(data[i]["url"]),
// leading: CircleAvatar(
// backgroundImage:
// NetworkImage(data[i]["picture"]["thumbnail"]),
// ),
onTap: () {
Navigator.push(
context, MaterialPageRoute(builder: (BuildContext context) => SecondPage(data[i])));
},
);
}),
),
],
),
),
);
}
}
class SecondPage extends StatefulWidget {
Map data;
SecondPage(this.data);
_SecondState createState() => _SecondState();
}
class _SecondState extends State<SecondPage> {
#override
void initState() {
super.initState();
_fetchPost();
}
Map post;
bool isLoad = true;
_fetchPost() async {
setState(() {
isLoad = true;
});
var url = widget.data["url"];
debugPrint(url);
final response = await http.get(url);
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON.
post = json.decode(response.body.toString());
setState(() {
isLoad = false;
});
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(widget.data["name"] + ' - ' + widget.data["url"])),
body: _buildPokemon(context),
);
}
Widget _buildPokemon(BuildContext context) {
if (isLoad) return Center(child: CircularProgressIndicator());
return Container(
padding: EdgeInsets.all(10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(post['name']),
Text(post['weight'].toString()),
Text(post['height'].toString()),
Image.network(post['sprites']['front_default'])
],
),
);
}
}