I am trying to fetch the data from API using StreamBuilder, Kindly help with this error
Future<dynamic>' is not a subtype of type 'Stream<List<dynamic>>.
Basically we are fetching data and displaying data with help of ListView.buider and StreamBuilder:
Search_product.dart
import 'dart:async';
import 'package:beauty/user.dart';
import 'package:flutter/material.dart';
import 'package:beauty/backend.dart';
class SearchProduct extends StatefulWidget {
@override
_SearchProductState createState() => _SearchProductState();
}
class _SearchProductState extends State<SearchProduct> {
List<Welcome> _welcome;
Backend backend = new Backend();
bool waiting = true;
Stream _stream;
@override
void initState() {
// TODO: implement initState
super.initState();
Backend.getData().then((welcome) {
setState(() {
_welcome = welcome;
waiting = false;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFEBEAEF),
appBar: AppBar(
title: Row(children: [
SizedBox(
width: 70.0,
),
Text(
'Search Product',
style: TextStyle(
color: Colors.black,
),
),
SizedBox(
width: 70.0,
),
Flexible(
child: CircleAvatar(
child: Image.asset('assets/her.png'),
),
),
]),
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.black,
),
onPressed: () {},
),
backgroundColor: Color(0xFFEBEAEF),
),
body: Column(children: [
Container(
color: Colors.white70,
child: TextField(
decoration: InputDecoration(
prefixIcon: Icon(
Icons.search,
color: Colors.grey,
),
hintText: 'Search for product',
contentPadding:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 20.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white70, width: 1.0),
borderRadius: BorderRadius.all(Radius.circular(12.0)),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.white70, width: 2.0),
borderRadius: BorderRadius.all(Radius.circular(12.0)),
),
),
style: TextStyle(color: Colors.black),
),
),
Container(
child: waiting
? SizedBox(
width: 50,
height: 50,
child: CircularProgressIndicator(),
)
: Expanded(
child: StreamBuilder(
stream: Backend.getData(),
builder: (BuildContext context,
AsyncSnapshot<List<dynamic>> snapshot) {
return ListView.builder(
padding: EdgeInsets.all(8),
itemCount: null == _welcome ? 0 : _welcome.length,
itemBuilder: (BuildContext context, int index) {
Welcome welcome = _welcome[index];
return Card(
child: Column(
children: <Widget>[
ListTile(
leading: CircleAvatar(
radius: 30,
backgroundImage: NetworkImage(snapshot
.data[index].welcome.image),
),
title: Text(
snapshot.data[index].welcome.title),
subtitle: Text(snapshot
.data[index].welcome.description),
trailing: Text(snapshot
.data[index].welcome.price
.toString()),
)
],
),
);
});
}),
),
),
]));
}
}
Backend.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:beauty/user.dart';
class Backend {
static getData() async {
try {
var url = Uri.parse('https://fakestoreapi.com/products');
var response = await http.get(url);
if (response.statusCode == 200) {
return welcomeFromJson(response.body);
} else {
List error_message = ['error'];
return error_message;
}
} catch (e) {
print(e);
}
}
}
user.dart
import 'dart:convert';
List<Welcome> welcomeFromJson(String str) =>
List<Welcome>.from(json.decode(str).map((x) => Welcome.fromJson(x)));
String welcomeToJson(List<Welcome> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Welcome {
Welcome({
this.id,
this.title,
this.price,
this.description,
this.category,
this.image,
this.rating,
});
int id;
String title;
double price;
String description;
Category category;
String image;
Rating rating;
factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
id: json["id"],
title: json["title"],
price: json["price"].toDouble(),
description: json["description"],
category: categoryValues.map[json["category"]],
image: json["image"],
rating: Rating.fromJson(json["rating"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"title": title,
"price": price,
"description": description,
"category": categoryValues.reverse[category],
"image": image,
"rating": rating.toJson(),
};
}
enum Category { MEN_S_CLOTHING, JEWELERY, ELECTRONICS, WOMEN_S_CLOTHING }
final categoryValues = EnumValues({
"electronics": Category.ELECTRONICS,
"jewelery": Category.JEWELERY,
"men's clothing": Category.MEN_S_CLOTHING,
"women's clothing": Category.WOMEN_S_CLOTHING
});
class Rating {
Rating({
this.rate,
this.count,
});
double rate;
dynamic count;
factory Rating.fromJson(Map<String, dynamic> json) => Rating(
rate: json["rate"].toDouble(),
count: json["count"],
);
Map<String, dynamic> toJson() => {
"rate": rate,
"count": count,
};
}
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
CodePudding user response:
The response type from Backend.getData
is a Future, not a Stream.
Replace
StreamBuilder(
stream: Backend.getData(),
builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
with
FutureBuilder(
future: Backend.getData(),
builder: (BuildContext context, AsyncSnapshot<List<dynamic>> snapshot) {
//show visual loading
if(!snapshot.hasData) return Center(child: CircularProgressIndicator());
CodePudding user response:
I think that the error may be caused by the getData
function where you are returning a Future<dynamic>
(because you do not specify any return type) and passing this output to the StreamBuilder
initializer as stream
parameter that requires a Stream
type.
Note also that the getData
function is an async function so to get any output you need to await
for it.