I have a problem to make UI in flutter still update in realtime, I got the data from JSON web, made by node JS and MySQL.
Here my UI looks like. Image Shown null
I don't know why it happens. at first, navigate to that page it appears null, then I back to the previous page and do the same way, and it works the data appears. Image shows Data
My question is how to make the data always update in realtime?
here my code
import 'package:crophero/detail.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:crophero/home_page.dart';
import 'package:crophero/login_page.dart';
import 'package:crophero/api_provider.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
import 'dart:io';
class SensorPage extends StatefulWidget {
SensorPage({Key key, this.id, this.gh, this.idgh, this.namagh})
: super(key: key);
final int id;
final int idgh;
final String namagh;
final List gh;
static String tag = 'sensor-page';
#override
_SensorPageState createState() => new _SensorPageState();
}
Timer timer;
int suhu;
int rh;
int cahaya;
int air;
int tanah;
int angin;
class _SensorPageState extends State<SensorPage> {
Future loadSensor() async {
var jsonString = await http
.get('$endPoint/data_realtime?user_id=$id&&gh_id=${widget.idgh}');
final jsonResponse = json.decode(jsonString.body);
setState(() {
suhu = jsonResponse['suhu'];
rh = jsonResponse['rh'];
cahaya = jsonResponse['cahaya'];
air = jsonResponse['air'];
tanah = jsonResponse['tanah'];
angin = jsonResponse['angin'];
});
}
#override
void initState() {
super.initState();
loadSensor();
_buatlist();
}
#override
void dispose() {
super.dispose();
timer.cancel();
}
List<Container> daftarSensor = new List();
var karakter = [
{
"nama": "Air Temperature",
"gambar": "temp.png",
"warna": 0xFFD50000,
"nilai": "$suhu *C"
},
{
"nama": "Relative Humidity",
"gambar": "rh.png",
"warna": 0xFF33691E,
"nilai": "$rh %"
},
{
"nama": "Water Temperature",
"gambar": "water.png",
"warna": 0xFF0288D1,
"nilai": "$air *C"
},
{
"nama": "Light Intensity",
"gambar": "light.png",
"warna": 0xFFFFAB00,
"nilai": "${cahaya} lux"
},
{
"nama": "Soil Moisture",
"gambar": "soil.png",
"warna": 0xFF795548,
"nilai": "$tanah"
},
{
"nama": "Wind Velocity",
"gambar": "wind.png",
"warna": 0xFF00695C,
"nilai": "${angin} m/s"
},
];
_buatlist() async {
for (var i = 0; i < karakter.length; i++) {
final karakternya = karakter[i];
final data = karakter[i];
final String gambar = karakternya["gambar"];
daftarSensor.add(
new Container(
padding: new EdgeInsets.all(10.0),
child: new Column(
children: <Widget>[
new Material(
child: new Column(
children: <Widget>[
MaterialButton(
minWidth: 200.0,
height: 75.0,
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new Detail(
gambar: karakternya["gambar"],
warna: karakternya["warna"],
nilai: data["nilai"],
nama: karakternya["nama"],
idgh: widget.idgh,
namagh: widget.namagh,
)));
},
child: Column(
children: <Widget>[
Row(
children: <Widget>[
new Image.asset(
"img/$gambar",
fit: BoxFit.cover,
width: 50,
),
SizedBox(width: 130),
Text((karakternya["nilai"]),
style: TextStyle(
color: Colors.white,
fontSize: 25,
),
textAlign: TextAlign.left),
],
),
Text((karakternya["nama"]),
style: TextStyle(
color: Colors.white,
fontSize: 14,
),
textAlign: TextAlign.end),
],
),
)
],
),
color: Color(karakternya["warna"]),
borderRadius: BorderRadius.circular(20),
),
],
),
),
);
}
}
#override
Widget build(BuildContext context) {
return new Scaffold(
bottomNavigationBar: Container(
height: 50,
child: BottomAppBar(
color: Colors.green[900],
child: new Center(
child: new Row(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 50.0),
),
],
),
),
),
),
backgroundColor: Colors.white,
appBar: new AppBar(
backgroundColor: Colors.green[900],
title: new Text(
"${widget.namagh} ",
style: new TextStyle(color: Colors.white),
),
),
body: new ListView(
children: daftarSensor,
),
);
}
}
It's showing null because the states not updated yet. Once you re-enter this page, it calls build() and will apply updated state(which is previously assigned from loadSensor()), so it's showing correctly.
What I noticed from your code, there is no guarantee that _buatlist() will be called after loadSensor(). Since _buatlist() is expecting to see newly updated value from loadSensor(), they should work asynchronously.
So try put daftarSensor to your state group, and once new items loaded from loadSensor(), call _buatlist() to build dafterSensor and also call setState inside of _buatlist(), then it will update ListView.
Related
I am trying to build a product page with a datatable with the product´s aplicattions.
I want to filter using the product id, in this case "note.id". I don´tt know how and where to filter data, I can only show the full list. Any ideias?
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:catalogo/entities/note.dart';
import 'package:snapshot_carousel/snapshot_carousel.dart';
class ProductScreen extends StatefulWidget {
final Note note;
ProductScreen(this.note);
#override
_ProductScreenState createState() => _ProductScreenState(note);
}
class _ProductScreenState extends State<ProductScreen> {
final Note note;
List<Aplicacao> _aplicacoes = List<Aplicacao>();
List<Note> _aplicacoesDisplay = List<Note>();
_ProductScreenState(this.note);
Future<List<Aplicacao>> fetchNotes() async {
var data = await DefaultAssetBundle.of(context)
.loadString('assets/json/produtos.json');
var body = json.decode(data);
var aplicacoes = List<Aplicacao>();
for (var appliJson in body) {
aplicacoes.add(Aplicacao.fromJson(appliJson));
}
return aplicacoes;
}
#override
void initState() {
super.initState();
fetchNotes().then((value) {
setState(() {
_aplicacoes.addAll(value);
});
});
}
#override
Widget build(BuildContext context) {
final Color primaryColor =
Theme.of(context).primaryColor; // PEGA COR PRIMARIA DO TEMA
return Scaffold(
appBar: AppBar(
title: Text(note.id),
centerTitle: true,
),
body: ListView(
children: [
Padding(
padding: EdgeInsets.all(4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
SnapShotCarousel.snapShotCarousel([
Image.asset(
"assets/images/${note.imagem}",
//height: 300.0,
),
Image.asset(
"assets/images/${note.id}_1.png",
),
Image.asset(
"assets/images/${note.id}_2.png",
),
],
backgroundColor: Colors.white,
featureImageHeight: 400,
placeholderImageHeight: 60,
selectedImageBorderColor: Colors.green,
unselectedImageBorderColor: Colors.grey),
Text(
note.id,
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w500,
),
maxLines: 3,
),
DataTable(
headingTextStyle: Theme.of(context)
.textTheme
.overline
.copyWith(fontSize: 12.0),
showCheckboxColumn: false,
dataRowHeight: 54.0,
columns: [
DataColumn(label: Text('Segmento')),
DataColumn(label: Text('Montadora')),
DataColumn(label: Text('Veículo')),
DataColumn(label: Text('Motor')),
DataColumn(label: Text('Obs.')),
],
//rows: []
rows: _aplicacoes
.map((data) => DataRow(
cells: [
DataCell(Text(data.segmento)),
DataCell(Text(data.montadora)),
DataCell(Text(data.veiculo)),
DataCell(Text(data.motor)),
DataCell(Text(data.obs)),
]))
.toList(),
)
],
),
),
],
),
);
}
}
Below you can see the product page and the full aplicattions list.
You can try:
final _filteredList = _aplicacoes.where((product) => product.id == 'productID').toList();
This will provide you the list of products having product id = 'productID'.
I'm having trouble displaying 'option' and getting (print in terminal) the 'id' of the chosen option.
How can I retrieve the json as map and use it effectively in flutter_form_builder?
Here is the json object:
{
id: 7,
poll: What is the capital of Egypt?,
created_at: 2020-10-22 10:53:41,
votes_count: 4,
likes_count: 0,
options: [
{
id: 20,
option: Tunis,
pollId: 7,
votes_count: 1
}, {
id: 21,
option: Cairo,
pollId: 7,
votes_count: 3
}, {
id: 22,
option: New York,
pollId: 7,
votes_count: 0
}],
user_name: salem,
user_image: null,
topics: []
}
Here is my poll_details page:
import 'package:flutter/material.dart';
import 'package:circular_profile_avatar/circular_profile_avatar.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:like_button/like_button.dart';
import '../services/poll_services.dart';
import '../widgets/loading_widget.dart';
class PollDetails extends StatefulWidget {
final id;
PollDetails({this.id});
#override
_PollDetailsState createState() => _PollDetailsState(id);
}
class _PollDetailsState extends State<PollDetails> {
var id;
_PollDetailsState(this.id);
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
#override
void initState() {
super.initState();
optionsList.clear();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(title: Text("Details")),
body: FutureBuilder(
future: singlePoll(id),
builder: (context, snapshot) {
if(snapshot.hasData){
return ListView(
padding: EdgeInsets.fromLTRB(18, 40, 18, 0),
children: [
Padding(
padding: EdgeInsets.only(bottom: 20),
child: Container(
padding: EdgeInsets.fromLTRB(10, 40, 0, 40),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10.0),
border: Border.all(
color: Theme.of(context).primaryColor,
width: 5.0,
style: BorderStyle.solid
)
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if(imgPath(snapshot.data) == null) CircleAvatar(radius: 35,child: Image.asset('images/avatar.png'))
else CircularProfileAvatar(
imgPath(snapshot.data),
radius: 35,
borderWidth: 3.0,
borderColor: Colors.white,
backgroundColor: Colors.transparent,
foregroundColor: Colors.transparent,
errorWidget: (context, url, error) => Container(child: Icon(Icons.error)),
placeHolder: (context, url) => Container(
width: 50,
height: 50,
child: Text("Loading image..."),
)
),
SizedBox(width: 10.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
userName(snapshot.data),
style: TextStyle(fontSize: 20)
),
Flexible(
fit: FlexFit.loose,
child: Text(
votesCount(snapshot.data).toString()+" participants to this poll",
style: TextStyle(fontSize: 13)
)
)
]
)
)
]
)
)
),
///////////////////////////////// POLLS //////////////////////////////////////////////
FormBuilder(
key: _fbKey,
autovalidateMode: AutovalidateMode.always,
child: FormBuilderRadioGroup(
attribute: 'options',
decoration: InputDecoration(labelText: 'Choose only one:'),
validators: [FormBuilderValidators.required()],
orientation: GroupedRadioOrientation.vertical,
options: [
for (var i in optionsList) i['option'].toString()
]
.map((option) => FormBuilderFieldOption(value: option))
.toList(growable: false),
)
),
RaisedButton(
child: Text("Submit"),
onPressed: () async{
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
// Loading().show(context);
var option = _fbKey.currentState.value['options'];
print(option);
// var resp = await createPoll(question, tagS, choiceS);
// if(resp['status'] == "success"){
// Navigator.pop(context); //pop dialog
// } else {
// Navigator.pop(context); //pop dialog
// }
}
}
),
//////////////////////////// Like Button ///////////////////////////////
Row(
children: [
LikeButton(
size: 40,
circleColor:
CircleColor(start: Colors.red, end: Colors.red),
bubblesColor: BubblesColor(
dotPrimaryColor: Colors.red,
dotSecondaryColor: Colors.red,
),
likeBuilder: (bool isLiked) {
return Icon(
Icons.favorite,
color: isLiked ? Colors.red : Colors.grey,
size: 40,
);
},
likeCount: likes(snapshot.data),
countBuilder: (int count, bool isLiked, String text) {
var color = isLiked ? Colors.red : Colors.grey;
Widget result;
if (count == 0) {
result = Text(
"0",
style: TextStyle(color: color),
);
} else
result = Text(
text,
style: TextStyle(color: color),
);
return result;
}
),
Expanded(child: Text(" have liked this. Show some love, too!"))
]
),
Column(
children: [
// optionsList.forEach((element) => Text('option'))
for (var i in optionsList) Text(i['option'].toString())
]
),
RaisedButton(
child: Text("data"),
onPressed: (){singlePoll(id);}
)
]
);
}else {
return Center(child: CircularProgressIndicator());
}
}
)
)
);
}
}
And here is the request I use to get the response:
Future singlePoll(int id) async {
String url = baseUrl+"poll/get";
var stringID = id.toString();
var token = await storage.read(key: "jwt");
try{
final response = await http.post(
url,
headers: {'Accept':'application/json', 'Authorization':token},
body: {'pollId':stringID}
);
var dataToJson = jsonDecode(response.body);
for (var option in dataToJson['options']){
var optionID = option['id'];
var optionTitle = option['option'].toString();
var votesCount = option['votes_count'];
optionsList.add(option);
}
print(dataToJson);
return dataToJson;
} catch (e){
print('error caught: $e');
}
}
As you can see, I used a work around to get the list and display it.
Any suggestion is valuable.
Thanks in advance...
You need to use setState() in here:
setState() {
var optionID = option['id'];
var optionTitle = option['option'].toString();
var votesCount = option['votes_count'];
optionsList.add(option);
}
You can read more from the official document and look at here.
I try to edit data in mysql from flutter. I send Id from page one to page two And by id I Inquire about specific data then edit it With the condition where Id=Id. Now when the application works, I can make sure Id send to php file. I try here to update field of name.
Logcat
I/flutter: tappedddd http://xxxxxxxxx/ccv.php?id=66
I can see ID is sent with the link but data now do not change in the database.I don't know what is problem. Anyone know solution for this problem?
my full code:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
import 'MyPreferences.dart';
class Update extends StatefulWidget {
var getid;
Update({Key key, this.getid}) : super(key: key);
#override
_UpdateState createState() => new _UpdateState();
}
class _UpdateState extends State<Update> {
MyPreferences _myPreferences = MyPreferences();
var getid;
var _isLoading = false;
var data;
var _username = "";
var _phone = "";
var _password = "";
var image ="";
var _phoneController = new TextEditingController();
var _firstnameController = new TextEditingController();
var _lastnameController = new TextEditingController();
Future<String> _ShowDialog(String msg) async {
return showDialog<String>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return new AlertDialog(
title: new Text('Rewind and remember'),
content: new SingleChildScrollView(
child: new ListBody(
children: <Widget>[
new Text(msg),
],
),
),
actions: <Widget>[
new FlatButton(
child: new Text('Close'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
void _editData() async {
var url = "http://xxxxxxxx/ccv.php?id=${widget.getid}";
print("tappedddd $url");
var response = await http.post(url, body: {
"id": widget.getid,
// "id": _userController.text,
"name": _firstnameController.text,
// "name": _phoneController.text,
// "name": _lastnameController.text,
});
if (response.statusCode == 200) {
_ShowDialog("Updated Successfully");
} else {
_ShowDialog("Updated Failer");
}
//onEditedAccount();
//print(_adresseController.text);
}
_fetchData() async {
final url =
"http://xxxxxxxxxx/nhy.php?id=${widget.getid}";
final response = await http.get(url);
if (response.statusCode == 200) {
final map = json.decode(response.body);
final videosMap = map["result"];
setState(() {
_isLoading = true;
this.data = videosMap;
_username = data[0]['name'];
image = data[0]['image'];
print(data);
});
}
}
#override
void initState() {
super.initState();
_fetchData();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text("Update Profile"),
),
body: new Center(
child: data == null
? new CircularProgressIndicator()
: new ListView(
children: <Widget>[
new Padding(
padding: const EdgeInsets.fromLTRB(5, 100, 5, 5),
child: Column(
children: <Widget>[
new Padding(
padding:
const EdgeInsets.only(top: 20.0, bottom: 25.0),
child: Expanded(flex: 1,
child: Container(
child: Card(
child: new Padding(
padding: const EdgeInsets.all(5.0),
child: Image.network(
image,
width: 300,
height: 300,
fit: BoxFit.cover,
),
),
),
),
),
),
Card (
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Container(
margin: EdgeInsets.all(4),
child: TextField(
maxLength: 10,
decoration: InputDecoration(
labelText: ("name : "),
filled: true,
hintText: _username),
controller: _firstnameController,
),
),
SizedBox(
height: 5.0,
),
Container(
margin: EdgeInsets.all(4),
child: TextField(
maxLength: 8,
decoration: InputDecoration(
labelText: ("phone : "),
filled: true,
hintText: _phone),
controller: _phoneController,
),
),
SizedBox(
height: 5.0,
),
Container(
margin: EdgeInsets.all(4),
child: TextField(
maxLength: 8,
decoration: InputDecoration(
labelText: ("password : "),
filled: true,
hintText: _password),
controller: _lastnameController,
),
),
SizedBox(
height: 5.0,
),
]
)
),
SizedBox(
width: double.infinity,
child: new FlatButton(
child: const Text('Update'),color: Colors.amber,
padding: EdgeInsets.fromLTRB(100, 18, 100, 18),
onPressed: () { _editData();
},
),
),
SizedBox(
height: 10.0,
),
],
),
)
],
),
));
}
}
php file:
<?php
require_once 'connt.php';
$id=$_POST['id'];
$name =$_POST['name'];
$query="UPDATE topics SET name='$name' WHERE id='$id'";
$exeQuery = mysqli_query($con, $query) ;
if($exeQuery){
echo (json_encode(array('code' =>1, 'message' => 'Modifier avec succee')));
}else {echo(json_encode(array('code' =>2, 'message' => 'Modification Non Terminer')));
}
?>
I use the following code to generate 10 predefined cards on a flutter screen which doesn't change:
List cards = new List.generate(10, (i)=>new QuestionCard()).toList();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('My First App'),
backgroundColor:new Color(0xFF673AB7),
),
body: new Container(
child: new ListView(
children: cards,
)
)
);
}
}
class QuestionCard extends StatefulWidget {
#override
_QuestionCardState createState() => _QuestionCardState();
}
class _QuestionCardState extends State<QuestionCard> {
#override
Widget build(BuildContext context) {
return Container(
child: Card(
borderOnForeground: true,
color: Colors.green,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const ListTile(
trailing: Icon(Icons.album),
title: Text('Q1'),
subtitle: Text('What is the name of this location?'),
),
new TextFormField(
decoration: new InputDecoration(
labelText: "Answer Question",
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius: new BorderRadius.circular(25.0),
borderSide: new BorderSide(
),
),
//fillColor: Colors.green
),
validator: (val) {
if(val.length==0) {
return "Type your answer here";
}else{
return null;
}
},
keyboardType: TextInputType.text,
style: new TextStyle(
fontFamily: "Poppins",
),
),
ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('Save'),
onPressed: () {/* ... */},
),
],
),
],
),
),
);
}
}
My json is simple (questions.json):
{
"Questions":
[
{
"id" : 1,
"quest" : ["question one"]
},
{
"id" : 2,
"quest" : ["question two", "question three"]
},
{
"id" : 3,
"quest" : ["question four"]
},
{
"id" : 4,
"quest" : ["question five", "question six", "question seven"]
}
]
}
So I have 2 questions I need to solve:
1. If I have more than 1 question I'll need to add an additional text box for a response for which I'll use a different card type, 2, 3, 4 max, which I'll need to define once.
But my real question here:
How do I generate the list based on the json response:
Future _loadQuestionAssets() async
{
return await rootBundle.loadString('assets/questions.json');
}
Future loadQuestion() async{
String jsonString = await _loadQuestionAssets();
final jsonResponse = json.decode(jsonString);
Questions question = new Questions.fromJson(jsonResponse);
//List cards = new List.generate(length, generator)
}
try this:
class MyFirstApp extends StatefulWidget{
#override
createState()=> new _appState();
}
class _appState extends State<MyFirstApp>{
List _displayData;
//assuming that you saved your json file in your assets folder
loadJson() async {
String data = await rootBundle.loadString('assets/json/questions.json');
jsonResult = json.decode(data);
print(jsonResult);
setState((){
_displayData = jsonResult["Questions"];
});
}
#override
void initState(){
super.initState();
loadJson();
}
#override
Widget build(BuildContext context){
return Scaffold(
appbar: Appbar(
title: Text("My APP")
),
body: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: _displayData == null ? Center(child: CircularProgressIndicator()) :
ListView.builder(
itemcount: _displayData.length,
itembuilder: (context, index){
return Container(
width: MediaQuery.of(context).size.width,
height: 80,
margin: EdgeInsets.only(bottom: 5),
child: Text(_displayData[index]["id"])
);
}
)
)
);
}
}
I have a JSON file that has a text and each sentence is in a separate JSON object, the user shoud be able to navigate between sentenes with next() and previous() but when the app loads I get this error:
RangeError (index): Invalid value: Valid value range is empty: 0
until I press any other button on the screen that's when the text loads and get displayed.
The card itself is a statefulWidget and here's my code:
class _BottomCardsState extends State<BottomCards>{
bool isLoadingEnded = false;
Future<Null> getAllData() async{
await DefaultAssetBundle.of(context).loadString('assets/json/data.json').then((response){
isLoadingEnded = true;
var decodedData = json.decode(response);
for(Map d in decodedData){
dataList.add(Data.fromJson(d));
}
});
}
#override
void initState() {
super.initState();
getAllData();
}
int dataIndex = 0;
#override
Widget build(BuildContext context) {
int myNbr = dataList[dataIndex].id;
return Container(
child: Material(
color: Colors.transparent,
child: Card(
margin: EdgeInsets.symmetric(horizontal: 10.0),
elevation: 6.0,
child: Container(
alignment: Alignment.topCenter,
padding: EdgeInsets.symmetric(horizontal: 12.0,),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
splashColor: gradientStart,
icon: Icon(Icons.keyboard_arrow_left,),
onPressed: () {_previous();},
),
IconButton(
splashColor: gradientStart,
icon: Icon(Icons.keyboard_arrow_right,),
onPressed: () {_next();},
),
],
),
SizedBox(height: 4.0,),
isLoadingEnded == true ? Container(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: InkWell(
splashColor: Colors.lightBlue[100],
onTap: (){},
//the paragraph gets displayed here
child: Text(dataList[dataIndex].paragraph,
),
),
],
),
SizedBox(height: 8.0,),
Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Chip(
backgroundColor: secondaryDark,
label: Text('Number: $myNbr',
style: TextStyle(color: Colors.white, fontSize: 10.0, fontWeight: FontWeight.w500),),
),
],
),
],
),
): Center(child: loadingIndicator(),),
SizedBox(height: 6.0),
],
),
),
),
),
);
}
}
`
My JSON format:
{
"id": 1,
"paragraph": "lorem ipsum"
},
...
You need to wait until data is filled up.
change your getAllData method. Like,
Future<List<Data>> getAllData() async{
var response = await DefaultAssetBundle.of(context).loadString('assets/json/data.json')
var decodedData = json.decode(response);
for(Map d in decodedData){
dataList.add(Data.fromJson(d));
}
return dataList;
}
and now wait on build method. Like,
#override
Widget build(BuildContext context) {
return FutureBuilder<List<Data>>(
future: getAllData(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print("Here you can get data "+snapshot.data.toString());
//you can put your ui here
} else {
print("Waiting mode");
return Container(
color: Colors.blue,
);
}
},
)
}
import 'package:flutter/services.dart' show rootBundle;
the first of fall your data is like a map, and you are trying to store in a list. as I can see your data is the type of map.
{
"id": 1,
"paragraph": "lorem ipsum"
}
Future<void> getAllData() async {
final res= await rootBundle.loadString('assets/config.json');
final json = jsonDecode(res.body);
var parse = json as Map;
Data data=Data.fromJson(parse);
}
and if JSON is contained list data then
[
{
"id": 1,
"paragraph": "lorem ipsum"
},
{
"id": 1,
"paragraph": "lorem ipsum"
}
]
then
Future<void> getAllData() async {
final res= await rootBundle.loadString('assets/config.json');
final json = jsonDecode(res.body);
var parse = json as List;
parse.forEach((d){
dataList.add(Data.fromJson(d));
});
}