Futubuilder snapshot.hasData returning false - json

I wrote code to fetch data and put them to GridView Buider.
But condition snapshot.hasData not working, its always False and return CircularProgressIndicator().
But If I change condition to !snapshot.hasData(true) my code is working, and fetch data shows on the screen correctly.
Fetch API
List<String> pcBusy = [];
Future fetchDataStandart() async {
final urlAuth =
Uri.parse('http://xxx.xx.xxx.xxx/api/usersessions/activeinfo');
final response = await http
.get(urlAuth, headers: <String, String>{'authorization': basicAuth});
if (response.statusCode == 200) {
List listPc = List.from(json.decode(response.body)['result']);
pcBusy.clear();
for (int i = 0; i < listPc.length; i++) {
pcBusy.add(listPc[i]['hostName']);
}
print(pcBusy);
} else {
throw Exception('Error');
}
Builder code
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
'ЕВРОКО Стандарт',
),
),
body: FutureBuilder(
future: fetchDataStandart(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ComputerGrid();
} else {
return Center(
child: CircularProgressIndicator(),
);
}

Your fetchDataStandart() function does not have any return statement. Therefore calling it will not give you any data. You need to add a return statement. I do not know if you have just not shared the complete function, because one closing bracket is missing at the end.

Related

How to convert MQTT Message to JSON format in Flutter

I already connect and get data from MQTT broker using snapshot method. However, I want to convert the MQTT message to JSON format cause I want to do some condition code to certain data.
My problem is when I stream data from the MQTT broker, my data only came out for the last data for that index. That index consists three different data, but since the index hold 3 data at the same time, only the last data of the index that displayed. This is my current code. How can I do that?
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Flutter MQTT"),
),
body: FutureBuilder(
future: mqttSubscribe(topic: "/sensor_simulator/data"),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) {
return Center(
child: Text("Error: ${snapshot.error}"),
);
}
// if succeed to connect
if (snapshot.connectionState == ConnectionState.done) {
return StreamBuilder(
stream: snapshot.data,
builder: (BuildContext context, AsyncSnapshot snapshot) {
// if have error--> display
if (snapshot.hasError) {
return Center(
child: Text("Error: ${snapshot.error}"),
);
}
// if data detected--> display
if (snapshot.hasData) {
try {
final List<MqttReceivedMessage> receiveMessage =
snapshot.data;
final recMess =
receiveMessage[0].payload as MqttPublishMessage;
String payload = MqttPublishPayload.bytesToStringAsString(
recMess.payload.message);
return ListView(
children: [
Card(
child: ListTile(
title: Text(payload),
))
],
padding: EdgeInsets.all(10),
);
} catch (e) {
return Center(
child: Text("Error: ${e.toString()}"),
);
}
}
return Center(child: CircularProgressIndicator());
},
);
}
return Center(child: CircularProgressIndicator());
},
),
);
}
}
You can use this piece of code:
void _subscribeToTopic(String topicName) {
print('MQTTClientWrapper::Subscribing to the $topicName topic');
client.subscribe(topicName, MqttQos.atMostOnce);
client.updates!.listen((List<MqttReceivedMessage<MqttMessage>> c) {
final recMess = c[0].payload as MqttPublishMessage;
String message =
MqttPublishPayload.bytesToStringAsString(recMess.payload.message);
String decodeMessage = Utf8Decoder().convert(message.codeUnits);
print("MQTTClientWrapper::GOT A NEW MESSAGE $decodeMessage");
});
}

infinite loading for json data in flutter

EDIT - "When I tried to run print(snapshot.error), It gave "type int is not a subtype of type string""
I am trying to get json data from https://raw.githubusercontent.com/RahulBagdiOfficial/rto_app_flutter/master/assets/json/applyonline.json
using https request package then parsing it into json data,
I am using it to build a list using ListView.builder
that if the data is null return CircularProgressIndicator
and if it contain data return list
The problem is This
its Stuck on loading
This is my code
class ApplyOnline extends StatefulWidget {
#override
_ApplyOnlineState createState() => _ApplyOnlineState();
}
class _ApplyOnlineState extends State<ApplyOnline> {
#override
Future<List<ApplyOnlineList>> _getapplyonlinelist() async {
var data = await http.get(
"https://raw.githubusercontent.com/RahulBagdiOfficial/rto_app_flutter/master/assets/json/applyonline.json");
var jsonData = json.decode(data.body);
List<ApplyOnlineList> applyonlinelist = [];
for (var i in jsonData) {
ApplyOnlineList applyonlineobject =
ApplyOnlineList(i['index'], i['string'], i['url']);
applyonlinelist.add(applyonlineobject);
}
print(applyonlinelist.length);
return applyonlinelist;
}
Widget customURLButton(String text, String URL, Icon icon) {
;
}
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xff655ee6),
appBar: AppBar(
backgroundColor: Color(0xff655ee6),
title: Text("Apply Online"),
),
body: SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: FutureBuilder(
future: _getapplyonlinelist(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
} if(snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].string),
);
},
);
}
},
),
),
),
);
}
}
class ApplyOnlineList {
final int index;
final String url;
final String string;
ApplyOnlineList(this.url, this.index, this.string);
}
You should pass reference of the future since you're not accepting any params in future:
future: _getapplyonlinelist
Check all the connection state before getting into snapshot.
And for checking snapshot, You can do this way:
if(snapshot.hasData) {
// return something
} else if(snapshot.hasError) {
// play with error
}
return CircularProgressIndicator();
The problem is, you're checking for null, and returning the widget, doing this doesn't allow the FutureBuilder to rebuild because you're not checking its connection state, so the state of the data won't update. Try this instead.
...
FutureBuilder(
future: _getapplyonlinelist(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting || !snapshot.hasData)
{
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].string),
);
);
}
...
Checking the ConnectionState will let the future builder resolve the future properly.
future: _getapplyonlinelist(),
Don't do this. This way, every time your build function is called, your Future will start over. You need to start it once and then wait for it.
In your state, outside the build method, have a variable to hold the future. Assign _getapplyonlinelist() to this variable once, probably in the void initState () method. Then use that variable in your build method. That way, no matter how often the build method is called, it will not start the Future over and over and over.
In your state class:
Future<List<ApplyOnlineList>> waitingForOnlineList;
void initState () {
waitingForOnlineList = _getapplyonlinelist();
}
... and then in your build method:
future: waitingForOnlineList,

Flutter http get json data

I am having difficulty with data get. I am very new to Flutter and although I read the articles, I could not overcome this problem. I was able to get the data individually, but I couldn't put it in a loop. The codes are below.
Future<List<Post>> getPosts() async {
var jsonData = await http.get("https://example.com/api/posts.php");
final jsonResponse = json.decode(jsonData.body);
Match postList= Post.fromJsonMap(jsonResponse);
return (jsonResponse as List)
.map((postList) => Post.fromJsonMap(postList))
.toList();
//print("post" + postList.result[1].home);
}
When I run the print method, I can print the data. However, when I send it to futurebuilder, the data is not coming.
body: FutureBuilder(
future: getPosts(),
builder: (BuildContext context, AsyncSnapshot<List<Post>> snapshot) {
if (snapshot.hasData) {
print("test");
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index].result[index].home),
subtitle: Text(snapshot.data[index].result[index].title),
leading: CircleAvatar(
child: Text(
snapshot.data[index].result[index].id.toString()),
),
);
});
} else {
return Center(child: CircularProgressIndicator());
}
}),
Note: The codes I used as an example: https://github.com/emrealtunbilek/flutter_json_http/blob/master/lib/remote_api.dart
Try add additional if branch like this
} else if (snapshot.hasError) {
print(snapshot.error);
} else {
You can use JsonToDart for parse data and cast to your model

Http request does not complete

I'm trying to get data from a csv file on the internet:
https://covid.ourworldindata.org/data/owid-covid-data.csv
If you clicked on it you might have noticed that it downloads automatically, which I think is the problem.
When I'm using the http library in dart to get this data, I only get back a small part of it at the beginning. The response.statusCode is still equal to 200 and everything else works as expected.
I think that the automatic download is part of the problem but I'm not sure how to fix that
Here is the code:
import 'package:http/http.dart' as http;
...
main(){
String url = 'https://covid.ourworldindata.org/data/owid-covid-data.csv';
http.Response response = await http.get(url);
print(response.body);
}
Here is an example with json format:
Future<Response> fetchData() async
{
return await http.get("https://covid.ourworldindata.org/data/owid-covid-data.json");
}
Then inside the build() method:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: FutureBuilder(
future: fetchData(),
builder: (context, AsyncSnapshot<Response> snapshot) {
if (snapshot.hasData) {
Map<String, dynamic> map =
Map.from(jsonDecode(snapshot.data.body));
return Text(map["LBN"]["continent"]);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return CircularProgressIndicator();
},
), // This trailing comma makes auto-formatting nicer for build methods.
));
}

Flutter Futurebuilder snapshot is null

I try to show the results from JSON in a ListView in Flutter with a FutureBuilder.
But the snapshot is null and the message that no data is available shows.
Here I try to fetch the data:
static Future _getBans() async {
Storage.getLoggedToken().then((token) async {
var body = {
"token": token
};
final response = await http.post('${URLS.BASE_URL}/punishments.php', headers: ApiService.header, body: json.encode(body));
if (response.statusCode == 200) {
List<Ban> bans = [];
var jsonData = json.decode(response.body)["bans"];
for(var b in jsonData){
Ban ban = Ban(b["player"], b["reason"], int.parse(b["end"]), b["by"]);
bans.add(ban);
}
print(response.body);
print(bans.length);
return bans;
} else {
return null;
}
});
}
from this JSON response
{"status":1,"msg":"OK","bans":[{"player":"DDOSAttacke","reason":"Hacking","end":"1579275471304","by":"DDOSAttacke"}],"mutes":[]}
My Futurebuilder. Here is snapshot null but the count of the elements is working.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Aktive Bans'),
),
body: Container(
child: FutureBuilder(
future: _getBans(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text('Keine aktiven Ban vorhanden')
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index].player),
);
},
);
}
},
),
),
);
}
Please try this. I think you'll have to use await keyword for the getLoggedToken mothod, the returnwill wait for the post before returning anything. But now you're returning before the getLoggedTokenfinishes his work. That is why you are always receiving null.
static Future _getBans() async {
var token = await Storage.getLoggedToken();
var body = {
"token": token
};
final response = await http.post('${URLS.BASE_URL}/punishments.php', headers: ApiService.header, body: json.encode(body));
if (response.statusCode == 200) {
List<Ban> bans = [];
var jsonData = json.decode(response.body)["bans"];
for(var b in jsonData){
Ban ban = Ban(b["player"], b["reason"], int.parse(b["end"]), b["by"]);
bans.add(ban);
}
print(response.body);
print(bans.length);
return bans;
} else {
return null;
}
}