How to implement JSON Response in Flutter carousel_slider 4.1.1 - flutter

I have this API https://questinternational.ph/api/get_hotelphotos
[{
"id": 1,
"photo": "https://images.unsplash.com/photo-1520342868574-5fa3804e551c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=6ff92caffcdd63681a35134a6770ed3b&auto=format&fit=crop&w=1951&q=80",
"price": 120.12
},
{
"id": 2,
"photo": "https://images.unsplash.com/photo-1522205408450-add114ad53fe?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=368f45b0888aeb0b7b08e3a1084d3ede&auto=format&fit=crop&w=1950&q=80",
"price": 4303.22
}]
How can I implement in carousel_slider 4.1.1
Using http request?

You can create a model and map the retrieved data with the API to facilitate further manipulation of the information in the code
class Hotel {
final int id;
final String photo;
final double price;
Hotel({
required this.id,
required this.photo,
required this.price,
});
factory Hotel.fromMap(Map<String, dynamic> map) {
return Hotel(
id: map['id'],
photo: map['photo'],
price: (map['price'] as num).toDouble(),
);
}
}
Now you can retrieve the list with a helper
import 'package:http/http.dart' as http;
import 'dart:convert';
class Helper {
static Future<List<Hotel>> getListHotel() async {
late List<Hotel> listHotels = [];
var url = Uri.parse("https://questinternational.ph/api/get_hotelphotos");
var response = await http.get(url);
var hotelMap = json.decode(response.body);
for (var item in hotelMap) {
listHotels.add(Hotel.fromMap(item));
}
return listHotels;
}
}
The view:
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
class TestPage extends StatefulWidget {
TestPage({Key? key}) : super(key: key);
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Image Slider demo')),
body: FutureBuilder(
future: Helper.getListHotel(),
builder: ((context, AsyncSnapshot<List<Hotel>> snapshot) {
var data = snapshot.data;
if (data == null) {
return Center(child: CircularProgressIndicator());
}
return CarouselSlider(
options: CarouselOptions(),
items: data
.map((item) => Container(
child: Image.network(item.photo,
fit: BoxFit.cover, width: 1000),
))
.toList(),
);
}),
),
);
}
}
But don't forget that it's just a proposal, because there are several ways to do it.

Related

Flutter: Stream data from rest api using Cubit

The idea is to fetch data from api continuously and show this data in screen, without need to fetch manually, like that if someone else perform a change on server data this change will be shown without user refreshing action.
The implementation is done in Flutter BLoC (cubit).
I have already get a console print of data in the cubit but I can't get same data in the BlocBuilder neither in the BlocListener.
My code is:
//data_repository.dart
import 'dart:async';
import 'data.dart';
class DataRepository {
final DataApi dataApi;
List<Map<String, dynamic>> formatedData = [];
final _controller = StreamController<List<Map<String, dynamic>>>();
DataRepository(this.dataApi) {
getData();
}
Future<void> getData() async {
Timer.periodic(Duration(seconds: 5), (timer) async {
formatedData.clear();
Map<String, dynamic> res = await dataApi.getData();
List<dynamic> data = res['data'];
for (var el in data) {
formatedData.add({'id': el['id'], 'name': el['name']});
}
_controller.add(formatedData);
});
}
#override
Stream<List<Map<String, dynamic>>> data() async* {
yield* _controller.stream;
}
#override
void dispose() => _controller.close();
}
Blockquote
This code is Data Repository it get data and make it available via a StreamController named "_controller";
Here data is got and controller is working perfectly.
My Cubit State is like this:
//data_list_state.dart
class DataListState extends Equatable {
final List<Map<String, dynamic>> data;
DataListState(this.data);
#override
List<Object> get props => [data];
DataListState copyWith({
List<Map<String, dynamic>>? data,
}) {
return DataListState(
data ?? this.data,
);
}
}
When I print within copyWith() I get updated data;
My Cubit code:
//data_list_cubit.dart
class DataListCubit extends Cubit<DataListState> {
DataListCubit(this.dataRepository) : super(DataListState([])) {
loadList();
}
final DataRepository dataRepository;
loadList() {
dataRepository.data().listen((event) {
if (event.isNotEmpty) {
emit(state.copyWith(data: dataRepository.formatedData));
}
});
}
}
When I print in loadList() I get the updated data;
My Screen Code:
//home.dart
class Home extends StatelessWidget {
const Home({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(children: [
BlocListener<DataListCubit, DataListState>(
listener: (context, state) {
if (state.data.isNotEmpty) print(state.data[0].toString());
},
child: BlocBuilder<DataListCubit, DataListState>(
builder: (context, state) {
if (state.data.isNotEmpty) print(state.data[0].toString());
return ListView(
shrinkWrap: true,
children: [
for (Map<String, dynamic> ff in state.data)
ListTile(
title: Text(ff['name']),
leading: Text(ff['id'].toString()),
),
],
);
},
),
),
]),
);
}
}
When I console print here I don't get data just for the first time, and after every 5 secondes (described in my getData()) I get updated data in all my codes excepting in the home.
Can you tell me if my cubit implementation is right ?
What should I do to make it work ?
Thanks in advance
You must add the BlocProvider above the BlocListener or BlocBuilder in HomePage.
tip: Learn BlocListener vs BlocBuilder vs BlocConsumer. All three must be enclosed in BlocProvider to work
class MyHomePage extends StatelessWidget {
DataRepository dataRepository = DataRepository();
#override
Widget build(BuildContext context) {
return SafeArea(
child: BlocProvider<DataListCubit>(
create: (context) => DataListCubit(dataRepository),
child: Scaffold(
body: BlocBuilder<DataListCubit, DataListState>(
builder: (context, state) {
print(state.data);
if (state.data.isNotEmpty) {
return ListView(
shrinkWrap: true,
children: [
for (Map<String, dynamic> ff in state.data)
ListTile(
title: Text(ff['name']),
leading: Text(ff['id'].toString()),
),
],
);
} else {
return const Center(
child: Text('No Data'),
);
}
},
),
),
),
);
}
}
Your Cubit State should be like below as you don't require
Equitable for state management in Cubit implementation
class DataListState {
const DataListState(this.data);
final List<Map<String, dynamic>> data;
DataListState copyWith({
List<Map<String, dynamic>>? data,
}) {
return DataListState(
data ?? this.data,
);
}
}
Full code
In absence of DataApi, I have structured the whole working code with random data as in below :
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Demo',
theme: ThemeData(),
home: MyHomePage(),
// home: VibrateHomepage(),
);
}
}
class MyHomePage extends StatelessWidget {
DataRepository dataRepository = DataRepository();
#override
Widget build(BuildContext context) {
return SafeArea(
child: BlocProvider<DataListCubit>(
create: (context) => DataListCubit(dataRepository),
child: Scaffold(
body: BlocBuilder<DataListCubit, DataListState>(
builder: (context, state) {
print(state.data);
if (state.data.isNotEmpty) {
return ListView(
shrinkWrap: true,
children: [
for (Map<String, dynamic> ff in state.data)
ListTile(
title: Text(ff['name']),
leading: Text(ff['id'].toString()),
),
],
);
} else {
return const Center(
child: Text('No Data'),
);
}
},
),
),
),
);
}
}
class DataRepository {
DataRepository() {
getData();
}
DataApi dataApi = DataApi();
List<Map<String, dynamic>> formattedData = [];
final _controller = StreamController<List<Map<String, dynamic>>>();
Future<void> getData() async {
Timer.periodic(const Duration(seconds: 5), (timer) async {
Map<String, dynamic> el = dataApi.getNew();
formattedData.add({'id': el['id'], 'name': el['name']});
_controller.add(formattedData);
});
}
Stream<List<Map<String, dynamic>>> data() async* {
yield* _controller.stream;
}
void dispose() => _controller.close();
}
class DataApi {
var rng = Random();
getNew() {
var rnd = rng.nextInt(100);
return {
"id": rnd,
"name": "Person " + rnd.toString()
};
}
}
class DataListState {
const DataListState(this.data);
final List<Map<String, dynamic>> data;
DataListState copyWith({
List<Map<String, dynamic>>? data,
}) {
return DataListState(
data ?? this.data,
);
}
}
class DataListCubit extends Cubit<DataListState> {
DataListCubit(this.dataRepository) : super(DataListState([])) {
loadList();
}
final DataRepository dataRepository;
loadList() {
dataRepository.data().listen((event) {
if (event.isNotEmpty) {
emit(state.copyWith(data: dataRepository.formattedData));
}
});
}
}

Flutter 'List<Post>' has no instance getter 'lenght'

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 want to Show Complex JSON Data in Flutter But Getting Nothing

I am trying to show the JSON data from a URL to my Flutter application and haven't found any solution yet.
How to show this data in the ListView in Flutter?
Here is my complete Flutter project code:
Main.dart
import 'package:flutter/material.dart';
import 'package:jsontest/Json.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Cricket',
theme: new ThemeData(
primarySwatch: Colors.green,
),
home: new JsonParseDemo(),
);
}
}
Match.dart Where Json Data is in organized form
import 'dart: convert';
Match matchesFromJson(String str) => Match.fromJson(json.decode(str));
String matchesToJson(Match data) => json.encode(data.toJson());
class Match {
Match({
this.name,
this.status,
});
String name;
String status;
factory Match.fromJson(Map<String, dynamic> json) => Match(
name: json["name"],
status: json["status"],
);
Map<String, dynamic> toJson() => {
"name": name,
"status": status,
};
}
Service.dart Here is the base URL to get JSON data
import 'package:http/http.dart' as http;
import 'Users.dart';
class Services {
//
static const String url = 'https://api.cricket.com.au/matches';
static Future<List<Match>> getMatches() async{
try{
final response = await http.get(url);
if (200 == response.statusCode){
final List<Match> match = matchesFromJson(response.body) as List<Match>;
return match;
}
else{
return List<Match>();
}
}
catch(e){
return List<Match>();
}
}
}
And here is the code of my main class where I want to show the data.
JsonParser.dart
import 'package:flutter/material.dart';
import 'Services.dart';
import 'Users.dart';
class JsonParseDemo extends StatefulWidget {
//
JsonParseDemo() : super();
#override
_JsonParseDemoState createState() => _JsonParseDemoState();
}
class _JsonParseDemoState extends State<JsonParseDemo> {
//
List<Match> _match;
bool _loading;
#override
void initState() {
super.initState();
_loading = true;
Services.getMatches().then((matches) {
setState(() {
_loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Matches'),
),
body: Container(
color: Colors.white,
child: ListView.builder(
itemCount: null == _match ? 0 : _match.length,
itemBuilder: (context, index) {
Match match = _match[index];
return ListTile(
title: Text(match.name),
subtitle: Text(match.status),
);
},
),
),
);
}
}
How to get "Name and Status" of the match from this JSON?
Try my code below :
json_parse_demo_screen.dart
class JsonParseDemo extends StatefulWidget {
//
JsonParseDemo() : super();
#override
_JsonParseDemoState createState() => _JsonParseDemoState();
}
class _JsonParseDemoState extends State<JsonParseDemo> {
//
List<Match> _match;
bool _loading = true;
#override
void initState() {
super.initState();
_loading = true;
Services.getMatches().then((matches) {
setState(() {
_match = matches;
_loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Matches'),
),
body: Container(
color: Colors.white,
child: ListView.builder(
itemCount: null == _match ? 0 : _match.length,
itemBuilder: (context, index) {
Match match = _match[index];
return ListTile(
title: Text(match.name),
subtitle: Text(match.status),
);
},
),
),
);
}
}
match.dart
import 'dart:convert';
String matchesToJson(Match data) => json.encode(data.toJson());
class Match {
Match({
this.name,
this.status,
});
String name;
String status;
factory Match.fromJson(Map<String, dynamic> json) => Match(
name: json["name"],
status: json["status"],
);
Map<String, dynamic> toJson() => {
"name": name,
"status": status,
};
}
service.dart
Here, you will have to check the hierarchy of the response you get.
The hierarchy of response is:
- meta
- matchList
- matches
Then you have to look for the result you expect (here matches)
class Services {
//
static const String url = 'https://api.cricket.com.au/matches';
static Future<List<Match>> getMatches() async{
try{
final response = await http.get(url);
final responseFormatted = json.decode(response.body);
final matches = responseFormatted["matchList"]["matches"];
if (200 == response.statusCode){
final List<Match> match = matches.map<Match>((item) => Match.fromJson(item)).toList();
return match;
}
else{
return List<Match>();
}
}
catch(e){
return List<Match>();
}
}
}
Output
You didn't initialize match
List<Match> _match;
You can do it like this
Services.getMatches().then((matches) {
setState(() {
_match=matches
_loading = false;
});
});

How can I get string value from API in flutter?

I am trying to get string value from the API to the list in a flutter.
Each time I try to get the list there is an exception "Unhandled Exception: type 'String' is not a subtype of type 'Map'"
the data I have is in the format given below:
{
"status": 1,
"data": [
"Chapter 1",
"Chapter 2",
]
}
Use this response class to load response and access all the variables.
class ResponseData {
String status;
List<String> data;
ResponseData({
this.status,
this.data,
});
factory ResponseData.fromJson(Map<String, dynamic> json) => ResponseData(
status: json["status"],
data: List<String>.from(json["data"].map((x) => x)),
);
}
Add our response json to ResponseData class
ResponseData responseDataFromJson(String responseFromServiceCall) => ResponseData.fromJson(json.decode(responseFromServiceCall));
From the above mentioned json i have created a sample json for ListView :
{
"status": 1,
"data": [
"Chapter 1",
"Chapter 2"
]
}
Creating a model class from the json :
// To parse this JSON data, do
//
// final data = dataFromJson(jsonString);
import 'dart:convert';
Data dataFromJson(String str) => Data.fromJson(json.decode(str));
String dataToJson(Data data) => json.encode(data.toJson());
class Data {
int status;
List<String> data;
Data({
this.status,
this.data,
});
factory Data.fromJson(Map<String, dynamic> json) => Data(
status: json["status"],
data: List<String>.from(json["data"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"status": status,
"data": List<dynamic>.from(data.map((x) => x)),
};
}
Parsing data and then rendering it on ui :
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dummy.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<String> dataList = List();
bool _isLoading = false;
#override
void initState() {
super.initState();
loadYourData();
}
Future<String> loadFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
loadYourData() async {
setState(() {
_isLoading = true;
});
String jsonString = await loadFromAssets();
final data = dataFromJson(jsonString);
// here you get the complete object
dataList = data.data;
setState(() {
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
child: _isLoading
? CircularProgressIndicator()
: ListView.builder(
itemCount: dataList.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(dataList[index]),
),
],
),
);
},
),
),
),
);
}
}
Following is the parse.json file :
And below is the pubspec file where you need to define the json folder :
Let me know if it works.

Flutter - How to load JSON into futurebuilder

I'm trying to create what should be a very simple flutter app that will load all data from a POST with parameters and create a scrolling list with the details.
currently I'm not getting any errors, however the loading circle just spins for ever even though the JSON has been successfully returned, any help or ideas would be greatly appreciated.
Here's what I have so far:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Post>> fetchPosts(http.Client client) async {
var url = "contacts.json";
var client = new http.Client();
var request = new http.Request('POST', Uri.parse(url));
var body = {'type': 'getContacts'};
request.bodyFields = body;
var data = http.post(url, body: {"type": "getContacts"})
.then((response) {
print(response.body);
return compute(parsePosts, response.body);
});
}
// A function that will convert a response body into a List<Photo>
List<Post> parsePosts(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Post>((json) => Post.fromJson(json)).toList();
}
class Post {
final String First;
final String Last;
final String Email;
final String Phone;
final String Photo;
final String Full;
Post({this.Full, this.First, this.Last, this.Photo, this.Email, this.Phone});
factory Post.fromJson(Map<String, dynamic> json) {
return new Post(
Full: json['Full'] as String,
First: json['First'] as String,
Last: json['Last'] as String,
Photo: json['Photo'] as String,
Email: json['Email'] as String,
Phone: json['Phone'] as String,
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final appTitle = 'CONTACTS';
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: FutureBuilder<List<Post>>(
future: fetchPosts(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? PhotosList(photos: snapshot.data)
: Center(child: CircularProgressIndicator());
},
),
);
}
}
class PhotosList extends StatelessWidget {
final List<Post> photos;
PhotosList({Key key, this.photos}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: photos == null ? 0 : photos.length,
itemBuilder: (BuildContext context, i) {
return new ListTile(
title: new Text(photos[i].Last + " " + photos[i].First),
subtitle: new Text(photos[i].Phone),
leading: new CircleAvatar(
backgroundImage:
new NetworkImage(photos[i].Photo),
)
);
}
);
}
}
Test JSON data as such:
[{
"Full": "Billy Bobbins",
"First": "Billy",
"Last": "Bobbins",
"Photo": "",
"Email": "billyb#here.com",
"Phone": "18885551212"
}, {
"Full": "Darron Dragonborn",
"First": "Darron",
"Last": "Dragonborn",
"Photo": "",
"Email": "dragond#here.com",
"Phone": "18005551111"
}]
Because you are using Future and async, you can use await for asynchronous operation.
So your fetchPosts should be like this
Future<List<Post>> fetchPosts(http.Client client) async {
var url = "contacts.json";
var client = new http.Client();
var request = new http.Request('POST', Uri.parse(url));
var body = {'type': 'getContacts'};
request.bodyFields = body;
var data = await http.post(url, body: {"type": "getContacts"});
print(data.body);
return await compute(parsePosts, data.body);
}
You can also refer to this.It is really helpful.
https://flutter.dev/docs/cookbook/networking/background-parsing