i'm following flutter offical docs to parse JSON in the background with the rest api from themoviedb. I get this following error when trying to show the list of movies
the api link : https://api.themoviedb.org/3/trending/movie/week?api_key=$apiKey
json data
app.dart'
simplify main.dart and isolate parsing using compute
import 'dart:convert';
import 'package:flutter/material.dart';
import 'models/movie_response.dart';
import 'package:auth_request/api_key.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
Future<List<Movie>> fetchMovies(http.Client client) async {
final response = await client
.get(Uri.parse('https://api.themoviedb.org/3/trending/movie/week?api_key=$apiKey'));
// Use the compute funtion to run fetchMovies in a separate isolate
return compute(parseMovies, response.body);
}
// A function that converts a response body into a List<Movie>.
List<Movie> parseMovies(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Movie>((json) => Movie.fromJson(json)).toList();
}
class MovieApp extends StatefulWidget {
const MovieApp({super.key});
#override
MovieAppState createState() => MovieAppState();
}
class MovieAppState extends State<MovieApp> {
late Future<Movie> futureAlbum;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MovieDB List',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('MovieDB List'),
),
body: Center(
child: FutureBuilder<List<Movie>>(
future: fetchMovies(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('${snapshot.error}');
} else if (snapshot.hasData) {
return MoviesList(movies: snapshot.data!);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
),
),
),
);
}
}
//
class MoviesList extends StatelessWidget {
const MoviesList({super.key, required this.movies});
final List<Movie> movies;
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemBuilder: (context, index) {
return Image.network(movies[index].original_title);
},
);
}
}
movie.dart
Parse and convert the JSON into a list of movies with the help of map and factory
class Movie {
final String original_title;
final String overview;
final String poster_path;
final String release_date;
const Movie({
required this.original_title,
required this.overview,
required this.poster_path,
required this.release_date,
});
factory Movie.fromJson(Map<String, dynamic> json) {
return Movie(
original_title: json['original_title'],
overview: json['overview'],
poster_path: json['poster_path'],
release_date: json['release_date'],
);
}
}
change this:
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
to
final parsed = jsonDecode(responseBody)['results'];
Related
I am receiving an error on line 16 : class _HomePageState extends State {
I have a build function already in a widget that I have posted below, and when I try to implement a build in the _HomePageState the code below is unable to run. Im unsure on how to fix this error and would appreciate any help!
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MaterialApp(
home: HomePage(),
debugShowCheckedModeBanner: false,
));
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future getUserData() async {
var response = await http.get(Uri.parse(
'https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41&hourly=temperature_2m'));
var jsonData = jsonDecode(response.body);
List users = (response.body as List?)
?.map((u) => User(
u['hourly'],
u['time'],
u['temperature_2m'],
u['longitude'],
u['generationtime_ms'],
u['hourly_units'],
u['latitude']))
.toList() ??
[];
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Rangers Tool'),
),
body: Center(
child: Card(
child: FutureBuilder(
future: getUserData(),
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return const Center(child:
CircularProgressIndicator());
} else {
return ListView.builder(
itemCount: snapshot.data?.length,
itemBuilder: (context, i) {
return ListTile(
title: Text(snapshot.data[i].longitude),
subtitle: Text(snapshot.data[i].latitude),
);
});
}
},
))),
);
}
getUserData() {}
class User {
final String? hourly,
time,
temperature_2m,
longitude,
generationtime_m,
hourly_units,
latitude;
User(this.longitude, this.latitude, this.hourly, this.time,
this.temperature_2m, this.generationtime_m, this.hourly_units);
}
Your build method is outside the scope of your state class.
I'm trying to fetch api images into the card widgets in flutter. I have services, model and photos_page class. I tried lot's of ways but still doesn't work.
final photoItem = snapshot.data[index].previewURL;
I think problem is that snapshot can't get data
that's my photos_page:
import 'dart:convert';
import 'package:abcde/services/photos_model.dart';
import 'package:abcde/services/photos_service.dart';
import 'package:abcde/widgets/card_widget.dart';
import 'package:flutter/material.dart';
class PhotosPage extends StatefulWidget {
PhotosPage({Key? key}) : super(key: key);
static const String pathId = 'Photos page';
#override
State<PhotosPage> createState() => _PhotosPageState();
}
class _PhotosPageState extends State<PhotosPage> {
PhotosService photosService = PhotosService();
#override
void initState() {
// TODO: implement initState
super.initState();
photosService.getPhotos();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Photos'),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(children: [
_getProductTypeList(),
]),
),
);
}
Widget _buildListItem(
BuildContext context, AsyncSnapshot<dynamic> snapshot, int index) {
final photoItem = snapshot.data[index].previewURL;
print('photoItem is $photoItem');
return photoCard(photoItem);
}
Widget _buildList(BuildContext context, AsyncSnapshot<dynamic> snapshot) {
var values = snapshot.data;
return ListView.builder(
// itemCount: snapshot.length,
itemBuilder: (context, index) {
return _buildListItem(context, snapshot, index);
},
);
/* return ListView(
children: snapshot!.map((data) => _buildListItem(context, data)).toList(),
);*/
}
//PhotosModel photosModel = PhotosModel();
Widget _getProductTypeList() {
return Expanded(
child: FutureBuilder(
future: photosService.getPhotos(),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: LinearProgressIndicator(),
);
}
return _buildList(context, snapshot);
},
),
);
}
}
that's my model class:
class PhotosModel {
String previewURL;
PhotosModel({required this.previewURL});
/* factory PhotosModel.fromJson(Map<dynamic, dynamic> json) => PhotosModel(
previewURL: json['previewURL'] as String,
);
Map<String, dynamic> toJson() {
return <String, dynamic>{'previewURL': previewURL};
}*/
/* #override
String toString() {
return 'PhotosModel{url: $previewURL}';
}*/
/*factory PhotosModel.fromJson(Map<String, dynamic> json) {
return PhotosModel(url: json['url'] as String);
}*/
factory PhotosModel.fromJson(Map<dynamic, dynamic> json) =>
_commentFromJson(json);
Map<dynamic, dynamic> toJson() => photosModelToJson(this);
}
PhotosModel _commentFromJson(Map<dynamic, dynamic> json) {
return PhotosModel(
previewURL: json['previewURL'],
);
}
Map<dynamic, dynamic> photosModelToJson(PhotosModel instance) => <dynamic, dynamic>{
'previewURL': instance.previewURL,
};
and that's my service class. I make a list getPhotos() method but doesn't work anyway.
import 'dart:convert';
import 'package:abcde/services/photos_model.dart';
import 'package:http/http.dart';
const MY_API_KEY = '26711456-bde74f403cb42e77029bc1678';
const appUrl = 'https://pixabay.com/api/';
class PhotosService {
Future getData(String url) async {
print('Calling url: $url');
final response = await get(Uri.parse(url));
if (response.statusCode == 200) {
return response.body;
} else {
print(response.statusCode);
}
}
List<PhotosModel> dataList = [];
Future<List<PhotosModel>> getPhotos({String? query}) async {
final photosData = await getData(
'$appUrl?&key=$MY_API_KEY&q=$query');
var data =json.decode(photosData);
data.forEach((element) {
dataList.add(PhotosModel.fromJson(element));
});
print('this is photos data: $photosData');
return dataList;
}
}
that's the error it shows me
The following NoSuchMethodError was thrown building:
The method '[]' was called on null.
Receiver: null
Tried calling:
and that's my card widget
import 'package:flutter/material.dart';
Widget photoCard(String url) {
return Card(
child: Image(
image: NetworkImage(url),
),
);
}
for api I use this web-page:
https://pixabay.com/api/docs/#api_search_images
thank you very much in advance
Working Example
main.dart
===============
import 'package:demo_app/photo_page.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const PhotosPage(),
);
}
}
==============
photo_service.dart
====================
import 'dart:convert';
import 'package:http/http.dart';
const apiKey = '26711456-bde74f403cb42e77029bc1678';
const appUrl = 'https://pixabay.com/api/';
class PhotosService {
Future getData(String url) async {
print('Calling url: $url');
final response = await get(Uri.parse(url));
if (response.statusCode == 200) {
return response.body;
} else {
print(response.statusCode);
}
}
List<PhotosModel> dataList = [];
Future<List<PhotosModel>> getPhotos(String query) async {
final photosData = await getData('$appUrl?key=$apiKey&q=$query');
var data = json.decode(photosData);
var items = data["hits"];
items.forEach((element) {
dataList.add(PhotosModel.fromJson(element));
});
print('this is photos data: $photosData');
return dataList;
}
}
class PhotosModel {
String previewURL;
PhotosModel({required this.previewURL});
factory PhotosModel.fromJson(Map<dynamic, dynamic> json) =>
_commentFromJson(json);
Map<dynamic, dynamic> toJson() => photosModelToJson(this);
}
PhotosModel _commentFromJson(Map<dynamic, dynamic> json) {
return PhotosModel(
previewURL: json['previewURL'],
);
}
Map<dynamic, dynamic> photosModelToJson(PhotosModel instance) =>
<dynamic, dynamic>{
'previewURL': instance.previewURL,
};
=========================
photo_page.dart
=============
import 'package:demo_app/photo_service.dart';
import 'package:flutter/material.dart';
class PhotosPage extends StatefulWidget {
const PhotosPage({Key? key}) : super(key: key);
static const String pathId = 'Photos page';
#override
State<PhotosPage> createState() => _PhotosPageState();
}
class _PhotosPageState extends State<PhotosPage> {
PhotosService photosService = PhotosService();
#override
void initState() {
super.initState();
photosService.getPhotos("flower");
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Photos'),
),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(children: [
_getProductTypeList(),
]),
),
);
}
Widget _buildListItem(
BuildContext context, AsyncSnapshot<dynamic> snapshot, int index) {
final photoItem = snapshot.data[index].previewURL;
print('photoItem is $photoItem');
return photoCard(photoItem);
}
Widget _buildList(BuildContext context, AsyncSnapshot<dynamic> snapshot) {
var values = snapshot.data;
return ListView.builder(
itemCount: snapshot.hasData ? snapshot.data.length : 0,
itemBuilder: (context, index) {
return _buildListItem(context, snapshot, index);
},
);
}
Widget _getProductTypeList() {
return Expanded(
child: FutureBuilder(
future: photosService.getPhotos("flower"),
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: LinearProgressIndicator(),
);
}
return _buildList(context, snapshot);
},
),
);
}
}
Widget photoCard(String url) {
return Card(
child: Image(
image: NetworkImage(url),
),
);
}
I want to fetch price data of trading pairs specified inpriceList from the public Binance API and create a dynamic List of Card widgets using API response.
I am failing at this step as the future argument of FutureBuilder does not accept the list of Futures : List<Future<PriceListItem>> pliList
Thank you.
My code:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
));
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class PriceListItem {
final String pair;
final String price;
PriceListItem({
required this.pair,
required this.price,
});
factory PriceListItem.fromJson(Map<String, dynamic> json) {
return PriceListItem(
pair: json['symbol'],
price: json['price'],
);
}
}
class _HomePageState extends State<HomePage> {
List<String> pairList = [
"USTBUSD",
"USTUSDT",
"USDCBUSD",
"USDCUSDT",
"BUSDUSDT",
"BTCBUSD",
"USTBTC",
"BTCUSDT",
"BTCUSDC",
];
late Future<PriceListItem> pli;
late List<Future<PriceListItem>> pliList;
Future<PriceListItem> fetchPrice(String ticker) async {
final response = await http.get(Uri.parse(
"https://api.binance.com/api/v3/ticker/price?symbol=$ticker"));
if (response.statusCode == 200) {
return PriceListItem.fromJson(jsonDecode(response.body));
} else {
throw Exception("Failed to fetch price data.");
}
}
#override
void initState() {
pliList = [];
for (int i = 0; i < pairList.length; i++) {
pli = fetchPrice(pairList[i]);
pliList.add(pli);
}
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("price tracker"),
),
body: Column(
children: [
FutureBuilder<PriceListItem>(
future: pliList, //The argument type 'List<Future<PriceListItem>>' can't be assigned to the parameter type 'Future<PriceListItem>?'.dartargument_type_not_assignable
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: 2,
physics: const ScrollPhysics(),
padding: const EdgeInsets.all(8),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text(snapshot.data!.price),
subtitle: Text(snapshot.data!.pair),
trailing: const Icon(Icons.currency_bitcoin),
onTap: () {},
),
);
},
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
)
],
),
);
}
}
Do it like this this:
FutureBuilder<List<PriceListItem>>(
future: Future.wait(pliList),
builder: (context, snapshot) {
}
https://api.flutter.dev/flutter/dart-async/Future/wait.html
I'm new to flutter. I am getting an error like this, can you help me?
I've been stuck in http for json for 5 days, the codes in the source don't work. :( L
It says list not entered but when I enter it does not accept it.
I don't know on which line the problem is, but I got a warning like.
"The following NoSuchMethodError was thrown building FutureBuilder(dirty, state: _FutureBuilderState#447cc):"
enter image description here
enter image description here
// To parse this JSON data, do
//
// final post = postFromJson(jsonString);
import 'dart:convert';
Post postFromJson(String str) => Post.fromJson(json.decode(str));
String postToJson(Post data) => json.encode(data.toJson());
class Post {
Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
int userId;
int id;
String title;
String body;
factory Post.fromJson(Map<String, dynamic> json) => Post(
userId: json["userId"],
id: json["id"],
title: json["title"],
body: json["body"],
);
Map<String, dynamic> toJson() => {
"userId": userId,
"id": id,
"title": title,
"body": body,
};
}
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:json_http_place_holder/post.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Future getData = Future(() => null);
var con = Uri.parse("https://jsonplaceholder.typicode.com/posts");
Future<List<Post>> fetchPost() async {
List<Post> result = <Post>[];
final response = await http.get(con);
if (response.statusCode == 200) {
List listPost = jsonDecode(response.body);
for (int i = 0; i < listPost.length; i++) {
Post item = Post.fromJson(listPost[i]);
result.add(item);
}
}
return result;
}
#override
void initState() {
// TODO: implement initState
super.initState();
getData = fetchPost();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter HTTP json',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
body: FutureBuilder(
future: getData,
builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (snapshot.connectionState == ConnectionState.none) {
return const Center(
child: Text("Bir hata meydana geldi"),
);
} else if (snapshot.connectionState == ConnectionState.done) {
return ListView.separated(itemBuilder: (context,index){
return ListTile(
leading: Icon(Icons.local_post_office),
title: Text(snapshot.data[index].title),
subtitle: Text(snapshot.data[index].body),
);
},separatorBuilder: (context,index)=>Divider(),
itemCount: snapshot.data.lenght,
);
}
//var d =jsonDecode(snapshot.data.body);
return Container();
},
),
),
);
}
}
You did not spell length well.
The error tells No such method on list lenght
The correct spelling for getting the method is .length
Change
itemCount: snapshot.data.lenght,
to
itemCount: snapshot.data.length,
In your main.dart,
FutureBuilder => separatorBuilder =>
itemCount: snapshot.data.lenght,
Change the itemCount from that to :
itemCount: snapshot.data.length,
I'm learning flutter and dart language and trying to apply bloc pattern by rxdart and show data in the page.
Can't get length or display a data in page stream builder and listview.builder because I receive error:
class 'Future<List<User>>' has no instance getter 'length'.
Receiver: Instance of 'Future<List<User>>'
Tried calling: length
My class user.dart
class User {
int id;
String name;
String username;
String email;
User({this.id, this.name, this.username, this.email});
User.fromJson(Map<String, dynamic> parsedJson) {
User(
id: parsedJson['id'],
name: parsedJson['name'],
username: parsedJson['username'],
email: parsedJson['email'],
);
}
}
// user_repo.dart
import 'package:learn_flutter_bloc/bloc_rx_example/User.dart';
import 'package:http/http.dart' as http;
import 'dart:async';
import 'dart:convert';
import 'package:learn_flutter_bloc/url.dart';
class UserRepo {
static Future<List<User>> getUsers() async {
final res = await http.get("https://jsonplaceholder.typicode.com/users");
List<User> users = [];
if (res.statusCode == 200) {
var data = jsonDecode(res.body);
for (var user in data) {
users.add(User.fromJson(user));
}
return users;
} else {
throw Exception("Error In Calling APi");
}
}
}
// user_bloc
import 'package:learn_flutter_bloc/bloc_base.dart';
import 'package:learn_flutter_bloc/bloc_rx_example/user_repo.dart';
import 'package:rxdart/subjects.dart';
class UserBloc extends BlocBase {
Subject _usersSubject = BehaviorSubject();
Stream get users => _usersSubject.stream;
getUsers() async {
var usersData = UserRepo.getUsers();
_usersSubject.add(usersData);
}
#override
dispose() {
_usersSubject.close();
}
}
final bloc = UserBloc();
// user_list_app.dart
import 'package:flutter/material.dart';
import 'package:learn_flutter_bloc/bloc_rx_example/user_bloc.dart';
class UserListApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Bloc Rx Example',
theme: ThemeData(
primaryColor: Colors.teal,
),
home: Scaffold(
appBar: AppBar(
title: Text('Bloc Rx Example'),
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.of(context).pop();
}),
),
body: UserList(),
),
);
}
}
class UserList extends StatefulWidget {
#override
_UserListState createState() => _UserListState();
}
class _UserListState extends State<UserList> {
#override
void dispose() {
bloc.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
bloc.getUsers();
return Padding(
padding: EdgeInsets.all(10.0),
child: StreamBuilder(
stream: bloc.users,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.weekend),
title: Text('${snapshot.data[index].name}'),
);
});
} else if (!snapshot.hasError) {
return Text(snapshot.error.toString());
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
);
}
}
While you are using StreamBuilder in the UI, Your getUsers() is returning Future<List<User>> . Return Stream<<List<User>> from getUsers() .
Fixed I problem was in bloc_user.dart misssing await
Future<List<User>> getUsers() async {
var usersData = UserRepo.getUsers();
print(usersData);
_usersSubject.sink.add(usersData);
}
to
Future<List<User>> getUsers() async {
var usersData = await UserRepo.getUsers();
print(usersData);
_usersSubject.sink.add(usersData);
}