Why can't I retreive my data? (Flutter-Rest API) - json

I've been trying to retreive data from my database using REST API. There are not error in my code but there is no data shown in my emulator and it keeps showing circular progress indicator (that means no data)
Is this because of token that I want to get from shared preferences? or something else?
This is my getToken code :
String token;
Future<String> getToken() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String token = prefs.getString("token");
return token;
}
This is my ShowPost code :
Future<List<Post>> showPosts() async {
String token = await getToken();
var data = await http.get(
"https://api-wisapedia.herokuapp.com/posts?sortBy=createdAt:desc",
headers: {HttpHeaders.authorizationHeader: 'Bearer $token'},
);
var dataDecoded = json.decode(data.body);
List<Post> posts = List();
dataDecoded.forEach((post) {
post.add(post["destination"], post["owner"], post["image"]);
});
return posts;
}
And this is my body code :
FutureBuilder(
future: showPosts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Card(
color: Color(0xFFE1F5FE),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: Image(
image: AssetImage('lib/images/pantai.jpg')),
title: Text(snapshot.data[index].title),
subtitle: Text(snapshot.data[index].destination),
),
ButtonTheme.bar(
// make buttons use the appropriate styles for cards
child: ButtonBar(
children: <Widget>[
FlatButton(
child: const Text('DETAILS'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return DetailPost();
}),
);
},
),
FlatButton(
child: const Text('JOIN'),
onPressed: () {
/* ... */
},
),
],
),
),
],
),
);
});
} else {
return Align(
alignment: FractionalOffset.center,
child: CircularProgressIndicator(),
);
}
})
How can I solve this?

remove the () in the future parameter of the future builder
future : showPosts not future :showPosts().
Edit :
replace FutureBuilder with FutureBuilder<List<Post>> and AsyncSnapshot with AsyncSnapshot<List<Post>> to specify the data type of the incoming data.

Related

I get this error "_TypeError (type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Iterable<dynamic>')" from api array call

I'm working on a app that you can read quran and bible from it and I'm pulling quran surahs and bible books from firebase and write that data to api so that I get all of chapters at once so I have quran and bible apis for it I take care of bible part but with quran json data has array that I want to retrieve all that array and data under that array but I come of to this error while doing it what I'm doing wrong ? if you can help me I really appreciate it thank you very much
my api code:
Future getQuran(String surah) async {
var uri = Uri.https(
'ajith-holy-bible.p.rapidapi.com',
'/${surah}',
);
var response = await http.get(uri, headers: {
'X-RapidAPI-Key': 'd88d0a8158mshb8b539da6b34179p137959jsn31258093d5c2',
'X-RapidAPI-Host': 'al-quran1.p.rapidapi.com'
});
print(response.statusCode);
print(response.body);
Map<String, dynamic> map = jsonDecode(response.body);
List myData = [];
for (var item in map["verses"]) {
myData.add(item);
}
return myData;
}
this is what api looks like:
id:114
surah_name:"AL-NĀS"
surah_name_ar:"الناس"
translation:"HUMANS"
type:"meccan"
total_verses:6
description:"The surah that opens with the mention of God as the Lord of Humans and teaches one to seek refuge in Him from the whisperings of Satan and those of evil jinn and people. It takes its name from the word “people” or “mankind” (al-nās) which recurs throughout the surah. This is another surah commonly used as an invocation against evil.The surah is also known as: All People, Humankind, Mankind, People, The Men."
▶
verses:{} 6 keys
▶
1:{} 4 keys
id:1.114
content:"قُل أَعوذُ بِرَبِّ النّاسِ"
translation_eng:"Say, ‘I seek the protection of the Lord of humans,"
transliteration:"qul ʾaʿūdhu bi-rabbi n-nāsi"
▶
2:{} 4 keys
id:2.114
content:"مَلِكِ النّاسِ"
translation_eng:"Sovereign of humans,"
transliteration:"maliki n-nāsi"
this is surahs page:
stream: FirebaseFirestore.instance.collection("quran").snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
final quran = snapshot.data!.docs[index];
return Padding(
padding: const EdgeInsets.all(4.0),
child: Card(
borderOnForeground: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SurahReading(
surah: quran["chapter"],
book: quran["surah"],
)));
},
child: Text(quran["surah"]),
),
],
),
),
);
});
this surahs reading page:
child: SingleChildScrollView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.vertical,
child: Column(
children: [
SingleChildScrollView(
physics: BouncingScrollPhysics(),
scrollDirection: Axis.vertical,
child: FutureBuilder(
future: Api().getQuran(widget.surah),
builder: (context, snapshot) {
final quran = snapshot.data;
if (snapshot.hasData) {
return Container(
child: ListView.builder(
itemCount: quran.length,
itemBuilder: (context, index) {
return Row(
children: [
Center(
child: Text(
quran[index]["content"],
style: TextStyle(fontSize: 15),
),
),
Center(
child: Text(
quran[index]["translation_eng"],
style: TextStyle(fontSize: 15),
),
),
],
);
},
),
);
}
return Center(
child: CircularProgressIndicator(),
);
}),
),
I did try to get all surahs all ayet from api but I come up to a error and I couldn't fix it
Ok ı figured it out if anyone come up to this error change for to foreach
map["verses"].forEach((key, value) {
myData.add(value);
});

How to send json data from on route to another route

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);
],
),
),
),
);
}
}

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");
});
}

Flutter - Read json from local file and search and update UI

I am reading a local json file in a provider
Future<List<ProductModel>> readJsonData() async {
final jsondata = await rootBundle.loadString('jsonData/products.json');
final list = json.decode(jsondata) as List<dynamic>;
var _listOfProducts = list.map((e) => ProductModel.fromJson(e)).toList();
return _listOfProducts;
}
and the search function
void searchProduct(String searchText) {
if (searchText == '') {
return;
}
final products = listProducts.where((product) {
final nameLowerCase = product.name!.toLowerCase();
final searchTextLowerCase = searchText.toLowerCase();
return nameLowerCase.contains(searchTextLowerCase);
}).toList();
_searchString = searchText;
listProducts = products;
notifyListeners();
}
and then rendering it like so:
Consumer<ProductsProvider>(builder: (context, productData, child) {
//print(productData.listProducts.toString());
return FutureBuilder(
future: _productsProvider.readJsonData(),
builder: (context, data) {
/// I BELIEVE THIS IS THE CAUSE WHY THE UI WON'T UPDATE
productData.listProducts = data.data as List<ProductModel>;
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: productData.listProducts.length,
itemBuilder: (context, index) => Card(
elevation: 3,
child: ListTile(
title: Text(productData.listProducts[index].name!),
),
),
),
);
});
})
search textfield onChange:
onChanged: (value) {
_productsProvider.searchProduct(value);
},
The search works but the UI doesn't change, the list doesn't get filtered because of the line after the comment (above). How do I deal with this so that I get all the items before search (or when the searchText is empty) and the filtered items(list) when there is a searchText?

How to read data from Real time database firebase using flutter with a complicated JSON tree

I am working on a flutter app and I found obstacles on how to read product_name and price from Firebase and display them in list
I tried this code but it returns the whole JSON tree as a Text
class _BeveragesProductsState extends State<BeveragesProducts> {
var _firebaseRef = FirebaseDatabase().reference().child('Products');
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text(' Beverages Products'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: StreamBuilder(
stream: _firebaseRef.onValue,
builder: (context, snap) {
if (snap.hasData &&
!snap.hasError &&
snap.data.snapshot.value != null) {
Map data = snap.data.snapshot.value;
List item = [];
print("data $data");
data.forEach(
(index, data) => item.add({"key": index, ...data}));
print(item);
return ListView.builder(
reverse: true,
itemCount: item.length,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
Text("$data"),
],
);
});
}
},
),
),
],
),
);
}
}
enter image description here