How to load a list of AudioSource from GraphQL API in Flutter - flutter

I have this code file that loads audio playlist files to the media player direct from the internet. So, I want to change instead of loading audio playlist files direct from the internet I want it to fetch from my GraphQL API using graphql_flutter 5.1.0 (https://pub.dev/packages/graphql_flutter) package from zino.company.
My question is how can I query the list of episodes to populate the _playlist AudioSource before the page loads completely?
I tried to use didChangeDependencies but the playlist was not populated after the page loaded. Also, the Tested hard code that I commented on the file works but still it is hard coded. When the playlist is loaded, the audio files are playable and all the buttons work. I have attached the media_player.dart file and snapshot of the app.
My GraphQL API request and response for the episodes is as follow;
graphql request
{
episodeByPodcast(podcast: 1){
id
title
synopsis
duration
filePath
host
guest
podcast {
id
podcastTitle
}
recorded
posted
}
}
graphql response
{
"data": {
"episodeByPodcast": [
{
"id": "1",
"title": "Episode 1",
"synopsis": "Hello World",
"duration": "18:59",
"filePath": "podcasts/episode_1.mp3",
"host": "John Doe",
"guest": "Jane Doe",
"podcast": {
"id": "1",
"podcastTitle": "Season 1"
},
"recorded": "2022-05-27",
"posted": "2022-05-27"
},
{
"id": "4",
"title": "Episode 2",
"synopsis": "Hello World",
"duration": "18:59",
"filePath": "podcasts/episode_2.mp3",
"host": "John Doe",
"guest": "Jane Doe",
"podcast": {
"id": "1",
"podcastTitle": "Season 1"
},
"recorded": "2022-05-27",
"posted": "2022-05-27"
},
{
"id": "5",
"title": "Episode 3",
"synopsis": "Hello World",
"duration": "41:02",
"filePath": "podcasts/episode_3",
"host": "John Doe",
"guest": "Jane Doe",
"podcast": {
"id": "1",
"podcastTitle": "Season 1"
},
"recorded": "2022-05-28",
"posted": "2022-05-28"
}
]
}
}
The media_player.dart file
import 'package:audio_service/audio_service.dart';
import 'package:audio_session/audio_session.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:just_audio/just_audio.dart';
import 'package:just_audio_background/just_audio_background.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
import 'package:app/screens/podcast/widgets/common.dart';
import 'widgets/control_buttons.dart';
// Tested hard code
// const pathPrefix = MediaEndpoint.url;
// final List<Map<String, dynamic>> episodes = [
// {
// "id": "1",
// "title": "Episode 1",
// "synopsis": "Hello World",
// "duration": "18:59",
// "filePath":
// "podcasts/episode_1.mp3",
// "host": "John Doe",
// "guest": "Jane Doe",
// "podcast": {"id": "1", "podcastTitle": "Season 1"},
// "recorded": "2022-05-27",
// "posted": "2022-05-27"
// },
// {
// "id": "4",
// "title": "Episode 2",
// "synopsis": "Hello World",
// "duration": "18:59",
// "filePath":
// "podcasts/episode_2.mp3",
// "host": "John Doe",
// "guest": "Jane Doe",
// "podcast": {"id": "1", "podcastTitle": "Season 1"},
// "recorded": "2022-05-27",
// "posted": "2022-05-27"
// },
// {
// "id": "5",
// "title": "Episode 3",
// "synopsis": "Hello World",
// "duration": "41:02",
// "filePath": "podcasts/episode_3.mp3",
// "host": "John Doe",
// "guest": "Jane Doe",
// "podcast": {"id": "1", "podcastTitle": "Season 1"},
// "recorded": "2022-05-28",
// "posted": "2022-05-28"
// }
// ];
// final ConcatenatingAudioSource _playlist = ConcatenatingAudioSource(
// children: [
// for (var episode in episodes)
// AudioSource.uri(
// Uri.parse('$pathPrefix${episode['filePath']}'),
// tag: MediaItem(
// id: episode['id'].toString(),
// album: episode['podcast']['podcastTitle'].toString(),
// title: episode['title'].toString(),
// artUri: Uri.parse(
// "https://mywebsite.com/uploads/2021/04/cover-art.png"),
// ),
// ),
// ],
// );
// - End of Tested hard code -
class MediaPlayer extends StatefulWidget {
static const routeName = '/media-player';
#override
_MediaPlayerState createState() => _MediaPlayerState();
}
class _MediaPlayerState extends State<MediaPlayer> {
var _isInit = true;
var _isLoading = false;
#override
void didChangeDependencies() {
if (_isInit) {
setState(() {
_isLoading = true;
});
setState(() {
_isLoading = false;
});
}
_isInit = false;
super.didChangeDependencies();
}
static int _nextMediaId = 0;
late AudioPlayer _player;
final _playlist = ConcatenatingAudioSource(
children: [
ClippingAudioSource(
start: const Duration(seconds: 60),
end: const Duration(seconds: 90),
child: AudioSource.uri(Uri.parse(
"https://mywebsite.com/podcasts/episode_1.mp3")),
tag: MediaItem(
id: '${_nextMediaId++}',
album: "Science Friday",
title: "A Salute To Head-Scratching Science (30 seconds)",
artUri: Uri.parse(
"https://mywebsite.com/uploads/2021/04/cover-art.png"),
),
),
AudioSource.uri(
Uri.parse("https://mywebsite.com/podcasts/episode_2.mp3"),
tag: MediaItem(
id: '${_nextMediaId++}',
album: "Science Friday",
title: "A Salute To Head-Scratching Science",
artUri: Uri.parse(
"https://mywebsite.com/uploads/2021/04/cover-art.png"),
),
),
AudioSource.uri(
Uri.parse(
"https://mywebsite.com/podcasts/episode_3.mp3"),
tag: MediaItem(
id: '${_nextMediaId++}',
album: "Science Friday",
title: "From Cat Rheology To Operatic Incompetence",
artUri: Uri.parse(
"https://mywebsite.com/uploads/2021/04/cover-art.png"),
),
),
AudioSource.uri(
Uri.parse(
"https://mywebsite.com/podcasts/episode_4.mp3"),
tag: MediaItem(
id: '${_nextMediaId++}',
album: "Public Domain",
title: "Nature Sounds",
artUri: Uri.parse(
"https://mywebsite.com/uploads/2021/04/cover-art.png"),
),
),
],
);
final int _addedCount = 0;
#override
void initState() {
super.initState();
_player = AudioPlayer();
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.black,
));
_init();
}
Future<void> _init() async {
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration.speech());
// Listen to errors during playback.
_player.playbackEventStream.listen((event) {},
onError: (Object e, StackTrace stackTrace) {
print('A stream error occurred: $e');
});
try {
await _player.setAudioSource(_playlist);
} catch (e, stackTrace) {
// Catch load errors: 404, invalid url ...
print("Error loading playlist: $e");
print(stackTrace);
}
}
#override
void dispose() {
_player.dispose();
super.dispose();
}
Stream<PositionData> get _positionDataStream =>
Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
_player.positionStream,
_player.bufferedPositionStream,
_player.durationStream,
(position, bufferedPosition, duration) => PositionData(
position, bufferedPosition, duration ?? Duration.zero));
#override
Widget build(BuildContext context) {
final playerData = ModalRoute.of(context)!.settings.arguments as Map;
return _isLoading
? const CircularProgressIndicator()
: Scaffold(
appBar: AppBar(
title: Text(
playerData['title'],
),
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: StreamBuilder<SequenceState?>(
stream: _player.sequenceStateStream,
builder: (context, snapshot) {
final state = snapshot.data;
if (state?.sequence.isEmpty ?? true) {
return const SizedBox();
}
final metadata = state!.currentSource!.tag as MediaItem;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Image.network(
metadata.artUri.toString())),
),
),
Text(metadata.album!,
style: Theme.of(context).textTheme.headline6),
Text(metadata.title),
],
);
},
),
),
ControlButtons(_player),
StreamBuilder<PositionData>(
stream: _positionDataStream,
builder: (context, snapshot) {
final positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition:
positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: (newPosition) {
_player.seek(newPosition);
},
);
},
),
const SizedBox(height: 8.0),
Row(
children: [
StreamBuilder<LoopMode>(
stream: _player.loopModeStream,
builder: (context, snapshot) {
final loopMode = snapshot.data ?? LoopMode.off;
const icons = [
Icon(Icons.repeat, color: Colors.grey),
Icon(Icons.repeat, color: Colors.orange),
Icon(Icons.repeat_one, color: Colors.orange),
];
const cycleModes = [
LoopMode.off,
LoopMode.all,
LoopMode.one,
];
final index = cycleModes.indexOf(loopMode);
return IconButton(
icon: icons[index],
onPressed: () {
_player.setLoopMode(cycleModes[
(cycleModes.indexOf(loopMode) + 1) %
cycleModes.length]);
},
);
},
),
Expanded(
child: Text(
"Playlist",
style: Theme.of(context).textTheme.headline6,
textAlign: TextAlign.center,
),
),
StreamBuilder<bool>(
stream: _player.shuffleModeEnabledStream,
builder: (context, snapshot) {
final shuffleModeEnabled = snapshot.data ?? false;
return IconButton(
icon: shuffleModeEnabled
? const Icon(Icons.shuffle,
color: Colors.orange)
: const Icon(Icons.shuffle, color: Colors.grey),
onPressed: () async {
final enable = !shuffleModeEnabled;
if (enable) {
await _player.shuffle();
}
await _player.setShuffleModeEnabled(enable);
},
);
},
),
],
),
SizedBox(
height: 240.0,
child: StreamBuilder<SequenceState?>(
stream: _player.sequenceStateStream,
builder: (context, snapshot) {
final state = snapshot.data;
final sequence = state?.sequence ?? [];
return ReorderableListView(
onReorder: (int oldIndex, int newIndex) {
if (oldIndex < newIndex) newIndex--;
_playlist.move(oldIndex, newIndex);
},
children: [
for (var i = 0; i < sequence.length; i++)
Dismissible(
key: ValueKey(sequence[i]),
background: Container(
color: Colors.redAccent,
alignment: Alignment.centerRight,
child: const Padding(
padding: EdgeInsets.only(right: 8.0),
child:
Icon(Icons.delete, color: Colors.white),
),
),
onDismissed: (dismissDirection) {
_playlist.removeAt(i);
},
child: Material(
color: i == state!.currentIndex
? Colors.grey.shade300
: null,
child: ListTile(
title:
Text(sequence[i].tag.title as String),
onTap: () {
_player.seek(Duration.zero, index: i);
},
),
),
),
],
);
},
),
),
],
),
),
);
}
}
App screenshot
media player app screenshot

Related

Flutter Auto Countdown Implementation for Fitness Workout

I'm working on a Flutter Workout App and I'm having some issues implementing the Workout Sequence and Timer.
I was able to implement the auto countdown and workout sequence however, the countdown skips numbers between and the workout sequence runs only for the first 2 sets.
For example, if an exercise has 4 sets, the cycle only runs for the first two and it's glitchy. I need help with optimized code to help me achieve the workout sequence
JSON DATA
{
"data": {
"day1": [
{
"id": 1,
"title": "Reclining Triceps Press",
"equipment": "Pull Up Bar",
"level": "Beginner",
"reps": "15",
"rest": "45 Seconds",
"sets": "4",
"image": "https://wicombit.com/demo/fitpro/images/exercise_1519941887.jpg",
"video": null,
},
{
"id": 10,
"title": "Plank with Arm Raise",
"equipment": "Pull Up Bar",
"level": "Intermediate",
"reps": "12",
"rest": "30 Seconds",
"sets": "3",
"image": "https://wicombit.com/demo/fitpro/images/exercise_1519938568.jpg",
"video": null,
},
{
"id": 3,
"title": "90-degree Static Hold",
"equipment": "Pull Up Bar",
"level": "Beginner",
"reps": "12",
"rest": "45 Seconds",
"sets": "3",
"image": "https://wicombit.com/demo/fitpro/images/exercise_1519940878.jpg",
"video": null,
},
{
"id": 5,
"title": "Single-arm Medicine Ball Pushup",
"equipment": "Kettlebells",
"level": "Elite",
"reps": "8",
"rest": "45 Seconds",
"sets": "3",
"image": "https://wicombit.com/demo/fitpro/images/exercise_1519940316.jpg",
"video": null,
"status": "draft"
}
],
}
}
I have tried the below implementation but not getting the results I want.
Dart Implementation
class WorkouStartSequenceScreen extends StatefulWidget {
final exercise;
WorkouStartSequenceScreen({super.key, required this.exercise});
#override
State<WorkouStartSequenceScreen> createState() =>
_WorkouStartSequenceScreenState();
}
class _WorkouStartSequenceScreenState extends State<WorkouStartSequenceScreen> {
late Timer _startTimer;
late Timer _restTimer;
late int totalNoOfExercisesInDay;
int currentExerciseIndex = 0;
late int totalNoOfSets;
late int totalNoOfReps;
late int totalRestTime;
int currentSetNo = 0;
int currentRepNo = 0;
int currentRestTime = 0;
bool dayWorkoutComplete = false;
int startUpCountdown = 10;
StreamController<int> _startEvents = BehaviorSubject();
StreamController<int> _restEvents = BehaviorSubject();
#override
void initState() {
totalNoOfExercisesInDay = widget.exercise.length;
totalNoOfReps = int.parse(widget.exercise[currentExerciseIndex].reps);
totalNoOfSets = int.parse(widget.exercise[currentExerciseIndex].sets);
totalRestTime = int.parse(widget.exercise[currentExerciseIndex].rest
.replaceAll(new RegExp(r'[^0-9]'), ''));
currentRestTime = totalRestTime;
_startEvents.add(startUpCountdown);
super.initState();
}
#override
void dispose() {
_startTimer.cancel();
_restTimer.cancel();
// _startEvents.close();
// _restEvents.close();
super.dispose();
}
void _showStartupDialog() async {
_startTimer = Timer.periodic(Duration(seconds: 1), (timer) {
(startUpCountdown > 0) ? startUpCountdown-- : _startTimer.cancel();
_startEvents.add(startUpCountdown);
});
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext builderContext) {
_startTimer = Timer(Duration(seconds: 10), () {
Navigator.of(context).pop();
});
return AlertDialog(
backgroundColor: AppStyles.primaryColor,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Your workout starts in',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white, fontSize: SizeConfig.font20)),
SizedBox(height: SizeConfig.height20),
StreamBuilder<int>(
stream: _startEvents.stream,
builder:
(BuildContext context, AsyncSnapshot<int> snapshot) {
return Text('${snapshot.data.toString()}',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: SizeConfig.font50));
}),
],
),
);
}).then((val) {
if (_startTimer.isActive) {
_startTimer.cancel();
}
});
}
void startRestTimer() async {
_restTimer = Timer.periodic(Duration(seconds: 1), (timer) {
(currentRestTime > 0) ? currentRestTime-- : _restTimer.cancel();
_restEvents.add(currentRestTime);
});
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext builderContext) {
_restTimer = Timer(Duration(seconds: totalRestTime), () {
Navigator.of(context).pop();
});
return AlertDialog(
backgroundColor: AppStyles.primaryColor,
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('REST',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white, fontSize: SizeConfig.font20)),
SizedBox(height: SizeConfig.height20),
StreamBuilder<int>(
stream: _restEvents.stream,
builder:
(BuildContext context, AsyncSnapshot<int> snapshot) {
return Text('${snapshot.data.toString()}',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: SizeConfig.font50));
}),
],
),
);
}).then((_) {
print("Next Set Starting");
setState(() {
currentRepNo = 0;
currentRestTime = int.parse(widget.exercise[currentExerciseIndex].rest
.replaceAll(new RegExp(r'[^0-9]'), ''));
startExercise();
});
_restTimer.cancel();
});
}
void startExercise() {
const oneSec = const Duration(seconds: 2);
new Timer.periodic(
oneSec,
(Timer timer) {
if (currentRepNo == totalNoOfReps) {
setState(() {
timer.cancel();
startRestTimer();
currentSetNo++;
if (currentSetNo == totalNoOfSets) {
currentExerciseIndex++;
}
});
} else {
setState(() {
currentRepNo++;
});
}
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blueGrey[100],
appBar: AppBar(
backgroundColor: AppStyles.primaryDark,
leading: GestureDetector(
onTap: () => Get.back(),
child: Icon(FontAwesomeIcons.xmark,
color: AppStyles.appSecondaryColor)),
),
body: Column(children: [
Image.network(widget.exercise[currentExerciseIndex].image),
SizedBox(height: SizeConfig.height20),
TitleTextWidget(
titleText: widget.exercise[currentExerciseIndex].title,
titleSize: SizeConfig.font25,
titleTextMaxLines: 3),
SizedBox(height: SizeConfig.height50),
Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
Column(children: [
Row(children: [
TitleTextWidget(
titleText: ("$currentRepNo"),
titleSize: SizeConfig.font80,
),
Text("/", style: TextStyle(fontSize: SizeConfig.font80)),
DescriptionTextWidget(
descriptionText: widget.exercise[currentExerciseIndex].reps,
descriptionSize: SizeConfig.font80,
fontFamily: 'Raleway'),
]),
SizedBox(height: SizeConfig.height20),
DescriptionTextWidget(
descriptionText: 'Reps',
fontFamily: 'Raleway',
descriptionSize: SizeConfig.font30)
]),
Column(children: [
Row(children: [
TitleTextWidget(
titleText: currentSetNo.toString(),
titleSize: SizeConfig.font80,
),
Text("/", style: TextStyle(fontSize: SizeConfig.font80)),
DescriptionTextWidget(
descriptionText: widget.exercise[currentExerciseIndex].sets,
descriptionSize: SizeConfig.font80,
fontFamily: 'Raleway'),
]),
SizedBox(height: SizeConfig.height20),
DescriptionTextWidget(
descriptionText: 'Sets',
fontFamily: 'Raleway',
descriptionSize: SizeConfig.font30)
])
]),
SizedBox(height: SizeConfig.height30),
GestureDetector(
onTap: () {
_showStartupDialog();
Future.delayed(const Duration(seconds: 10), () {
startExercise();
});
},
child: Container(
height: SizeConfig.height70,
width: double.maxFinite,
margin: EdgeInsets.symmetric(
horizontal: SizeConfig.width20, vertical: SizeConfig.height5),
decoration: BoxDecoration(
color: AppStyles.primaryColor,
borderRadius: BorderRadius.circular(
SizeConfig.radius15,
)),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: SizeConfig.width40,
vertical: SizeConfig.height10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(FontAwesomeIcons.play, color: Colors.white),
SizedBox(width: SizeConfig.width10),
Text(
"Start",
style: TextStyle(
color: Colors.white,
fontSize: SizeConfig.font25,
fontWeight: FontWeight.w500),
),
],
),
),
),
)
]),
);
}
}

Flutter : How to display sername,pname data from a model class(PokelistModel)?

I have created a PokelistModel class and I want to display data in ServiceRequestedPage. But I am unable to access sername,pname from the model class to display in ServiceRequestedPage.
API Responses:-
{
"service": [
{
"id": "444",
"user_id": "34856",
"service_provider_id": "289",
"address": "235, AH45, Doordarshan Colony, Gajapati Nagar, Bhubaneswar, Odisha 751013, India",
"date": "2022-03-28",
"entry_time": "2022-03-28 12:16:14",
"sername": "Barber",
"pname": "Sabita Panda",
"emaildta": "",
"paddress": "Bhubaneswar, Odisha, India",
"serphone": "9853575231",
"serimage": "default.png",
"review": [],
"total_rating": 0
},
{
"id": "441",
"user_id": "34856",
"service_provider_id": "287",
"address": "235, AH45, Doordarshan Colony, Gajapati Nagar, Bhubaneswar, Odisha 751013, India",
"date": "2022-02-02",
"entry_time": "2022-02-02 16:03:11",
"sername": "Aaya & Maid ",
"pname": "Rabi Panda",
"emaildta": "",
"paddress": " Bhubaneswar, Odisha, India",
"serphone": "9853578231",
"serimage": "default.png",
"review": [
{
"id": "41",
"user_id": "34856",
"service_provider_id": "287",
"total_rating": "5.00",
"review": "g",
"entry_time": "2022-03-22 16:45:41"
},
{
"id": "42",
"user_id": "34856",
"service_provider_id": "287",
"total_rating": "5.00",
"review": "nyc",
"entry_time": "2022-03-23 16:32:33"
}
],
"total_rating": 5
},
{
"id": "431",
"user_id": "34856",
"service_provider_id": "2722",
"address": "214, Acharya Vihar, Bhubaneswar, Odisha 751013, India",
"date": "2021-02-19",
"entry_time": "2021-02-19 22:05:09",
"sername": "Hair & Spa",
"pname": "Friends Hairstyle",
"emaildta": "",
"paddress": "Plot No-88/6, Jaydev Vhir Over Bridge, Acharya Vihar, Bhubaneshwar - 751013, Near Trupati Kalyani Mandap",
"serphone": "9090531519",
"serimage": "",
"review": [
{
"id": "37",
"user_id": "34856",
"service_provider_id": "2722",
"total_rating": "5.00",
"review": "super",
"entry_time": "2021-10-20 12:11:00"
},
{
"id": "38",
"user_id": "34856",
"service_provider_id": "2722",
"total_rating": "5.00",
"review": "super",
"entry_time": "2021-10-20 12:11:02"
},
{
"id": "43",
"user_id": "34856",
"service_provider_id": "2722",
"total_rating": "5.00",
"review": "superb ",
"entry_time": "2022-03-23 16:33:00"
}
],
"total_rating": 5
}
],
"status": 1,
"message": "3 Matches Found!",
"total_review": 3
}
PokelistModel:-
import 'dart:convert';
PokelistModel pokelistModelFromJson(String str) => PokelistModel.fromJson(json.decode(str));
String pokelistModelToJson(PokelistModel data) => json.encode(data.toJson());
class PokelistModel {
PokelistModel({
required this.service,
required this.status,
required this.message,
required this.totalReview,
});
List<Service> service;
int status;
String message;
int totalReview;
factory PokelistModel.fromJson(Map<String, dynamic> json) => PokelistModel(
service: List<Service>.from(json["service"].map((x) => Service.fromJson(x))),
status: json["status"],
message: json["message"],
totalReview: json["total_review"],
);
Map<String, dynamic> toJson() => {
"service": List<dynamic>.from(service.map((x) => x.toJson())),
"status": status,
"message": message,
"total_review": totalReview,
};
}
class Service {
Service({
required this.id,
required this.userId,
required this.serviceProviderId,
required this.address,
required this.date,
required this.entryTime,
required this.sername,
required this.pname,
required this.emaildta,
required this.paddress,
required this.serphone,
required this.serimage,
required this.review,
required this.totalRating,
});
String id;
String userId;
String serviceProviderId;
String address;
DateTime date;
DateTime entryTime;
String sername;
String pname;
String emaildta;
String paddress;
String serphone;
String serimage;
List<Review> review;
int totalRating;
factory Service.fromJson(Map<String, dynamic> json) => Service(
id: json["id"],
userId: json["user_id"],
serviceProviderId: json["service_provider_id"],
address: json["address"],
date: DateTime.parse(json["date"]),
entryTime: DateTime.parse(json["entry_time"]),
sername: json["sername"],
pname: json["pname"],
emaildta: json["emaildta"],
paddress: json["paddress"],
serphone: json["serphone"],
serimage: json["serimage"],
review: List<Review>.from(json["review"].map((x) => Review.fromJson(x))),
totalRating: json["total_rating"],
);
Map<String, dynamic> toJson() => {
"id": id,
"user_id": userId,
"service_provider_id": serviceProviderId,
"address": address,
"date": "${date.year.toString().padLeft(4, '0')}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}",
"entry_time": entryTime.toIso8601String(),
"sername": sername,
"pname": pname,
"emaildta": emaildta,
"paddress": paddress,
"serphone": serphone,
"serimage": serimage,
"review": List<dynamic>.from(review.map((x) => x.toJson())),
"total_rating": totalRating,
};
}
class Review {
Review({
required this.id,
required this.userId,
required this.serviceProviderId,
required this.totalRating,
required this.review,
required this.entryTime,
});
String id;
String userId;
String serviceProviderId;
String totalRating;
String review;
DateTime entryTime;
factory Review.fromJson(Map<String, dynamic> json) => Review(
id: json["id"],
userId: json["user_id"],
serviceProviderId: json["service_provider_id"],
totalRating: json["total_rating"],
review: json["review"],
entryTime: DateTime.parse(json["entry_time"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"user_id": userId,
"service_provider_id": serviceProviderId,
"total_rating": totalRating,
"review": review,
"entry_time": entryTime.toIso8601String(),
};
}
ServiceRequestedPage :-
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_rating_bar/flutter_rating_bar.dart';
import 'package:http/http.dart';
import 'package:newbharatbiz/Model%20Class/PokelistService.dart';
import 'package:newbharatbiz/Model%20Class/pokelist_model.dart';
import 'package:newbharatbiz/Screens/AddReviewPage.dart';
import 'package:newbharatbiz/Screens/RequestedServiceDetailsPage.dart';
import 'HomePage.dart';
import 'package:http/http.dart' as http;
class ServiceRequestedPage extends StatefulWidget {
#override
_YourWidgetState createState() => _YourWidgetState();
}
class _YourWidgetState extends State<ServiceRequestedPage> {
bool isLoading = false;
late Future<PokelistModel> pokelist;
#override
void initState() {
super.initState();
pokelist = PokelistService.getProducts();
}
Future delete_poke() async {
final String DeletePokeAPI =
"https://newbharatbiz.in/mobile_api/v4/delete_poke.php";
setState(() {
isLoading = true;
});
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
"Content-Type": "application/x-www-form-urlencoded"
};
final Map<String, dynamic> body = {
"id": "idd",
};
String encodedBody = body.keys.map((key) => "$key=${body[key]}").join("&");
//var jsonBody = json.encode(body);
Response response = await http.post(Uri.parse(DeletePokeAPI),
body: encodedBody, headers: headers);
var jsonResponse = jsonDecode(response.body);
print(jsonResponse);
if (response.statusCode == 200) {
setState(() {
isLoading = false;
});
// If the server did return a 201 CREATED response,
// then parse the JSON.
//return json.decode(response.body)['services'];
print(response);
// return CatwiseServiceModel.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 201 CREATED response,
// then throw an exception.
throw Exception('Failed to load.');
}
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => true,
child: Scaffold(
appBar: new AppBar(
title: new Text('Service Requested List'),
leading: new IconButton(
icon: new Icon(Icons.arrow_back_outlined),
onPressed: () {
Navigator.pop(
context, true); // It worked for me instead of above line
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
}),
),
body: SingleChildScrollView(
child:
Column(mainAxisAlignment: MainAxisAlignment.start, children: [
FutureBuilder<PokelistModel>(
future: pokelist,
builder: (BuildContext context, snapshot) {
if (snapshot.hasData) {
//print(idd(snapshot.data[0]));
return SingleChildScrollView(
child: Column(
children: <Widget>[
ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Container(
margin: EdgeInsets.zero,
child: Card(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
ListTile(
leading: CircleAvatar(
child: Image.asset(
"assets/dummyprofile.png",
fit: BoxFit.fill),
backgroundColor:
Colors.transparent,
),
title: Text(
sername(snapshot.data[index]),
style: TextStyle(
color: Colors.black87,
fontWeight:
FontWeight.bold,
fontSize: 16),
),
/*subtitle: Row(
children: <Widget>[
Text("M/S : ",
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 13)),
Text(pname(snapshot.data[index]),
style: TextStyle(
color: Colors.black87)),
],
),*/
subtitle: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text(
"M/S : " +
pname(snapshot
.data[index]),
style: TextStyle(
color: Colors.black,
fontSize: 14)),
SizedBox(height: 5),
Text(
"Phone No : " +
serphone(snapshot
.data[index]),
style: TextStyle(
color: Colors.black,
fontSize: 14)),
],
),
trailing: new IconButton(
icon: new Icon(Icons.close,
color: Colors.black87,
size: 30.0),
onPressed: () {
delete_poke();
},
)),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(
left: 10.0),
child: Text(
"Address : " +
paddress(
snapshot.data[index]),
style: TextStyle(
color: Colors.black,
fontSize: 14)),
),
SizedBox(height: 15),
Padding(
padding: const EdgeInsets.only(
left: 10.0, bottom: 10.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
SizedBox(
height: 30.0,
child: MaterialButton(
child: Text("Rating"),
textColor: Colors.white,
color: Color(0xFF00796B),
disabledColor:
Colors.blue,
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius.all(
Radius.circular(
10.0), // Change your border radius here
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
AddReviewPage(
sername: snapshot
.data[
index]
['sername'],
pname: snapshot
.data[
index]
['pname'],
),
),
);
},
),
),
SizedBox(width: 20),
SizedBox(
height: 30.0,
child: MaterialButton(
child: Text("View"),
textColor: Colors.white,
color: Color(0xFF00796B),
disabledColor:
Colors.blue,
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius.all(
Radius.circular(
10.0), // Change your border radius here
),
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
RequestedServiceDetailsPage(
sername: snapshot
.data[
index]
['sername'],
pname: snapshot
.data[
index]
['pname'],
paddress: snapshot
.data[
index][
'paddress'],
serphone: snapshot
.data[
index][
'serphone'],
),
),
);
},
),
),
// SizedBox(height: 10),
/* Button (),
RatingBar (),
Button ()*/
]),
)
])));
})
],
),
);
}
return const Center(
child: SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation(Colors.blue),
),
),
);
}
// By default, show a loading spinner.
),
Visibility(visible: isLoading, child: CircularProgressIndicator())
]),
)),
);
}
}
PokelistService:-
import 'dart:convert';
import 'package:http/http.dart';
import 'package:newbharatbiz/Model%20Class/pokelist_model.dart';
import 'package:http/http.dart' as http;
class PokelistService {
static Future<PokelistModel> getProducts() async {
final String ServiceAPI =
"https://newbharatbiz.in/mobile_api/v4/listing_poke.php";
final headers = {
'Content-Type': 'application/json',
'Accept': 'application/json',
"Content-Type": "application/x-www-form-urlencoded"
};
final Map<String, dynamic> body = {
"user_id": "34856",
};
String encodedBody = body.keys.map((key) => "$key=${body[key]}").join("&");
//var jsonBody = json.encode(body);
Response response = await http.post(Uri.parse(ServiceAPI),
body: encodedBody, headers: headers);
var jsonResponse = jsonDecode(response.body);
print(jsonResponse);
if (response.statusCode == 200) {
// If the server did return a 201 CREATED response,
// then parse the JSON.
//return json.decode(response.body)['services'];
print(json.decode(response.body));;
final body = json.decode(response.body);
return body.map(PokelistModel.fromJson);
// var data = json.decode(response.body)
// return CatwiseServiceModel.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 201 CREATED response,
// then throw an exception.
throw Exception('Failed to load.');
}
}
}
There are a few ways how to do it. You can try this one:
Change response model to incorporate all the data. Just copy and paste JSON that you received here: https://app.quicktype.io
Then change the part here:
Text(
snapshot.data[index].service.sername,
style: TextStyle(color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 16),
),
Use the same structure for any other data that you need. Maybe you could create more generic ApiService and pass the necessary variables as parameters, like this:
Future<ApiResponse?> post(String url, dynamic body,
{Map<String, String>? headers}) async {
print('API Post: ${this.url+url}');
try {
final response = await http.post(Uri.parse(this.url+url),
body: body,
headers: headers
);
if (response.statusCode == 200) {
String data = response.body;
final decodedData = jsonDecode(data);
print('API Post: $decodedData)');
final _apiResponse = ApiResponse.fromJson(decodedData);
return _apiResponse;
}
} catch(e) {
print('API Post: $e');
}
return null;
}
I accessed the array like this> List data = snapshot.data!.service; then will displaylike this> sername data[index].sername
List data = snapshot.data!.service;
sername data[index].sername

error: Null check operator used on a null value OR List<dynamic> is not a subtype of type Map<String, dynamic>

fetch Two different pages api with same uniq id
I want the user_uniq_id of the API of the button and the user_uniq_id of the API of the team_list to match and show the data of its user after the match.
this code is for first File
This code is of the button that is coming from the api
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:practice/left_team.dart';
import 'package:http/http.dart' as http;
class Button extends StatefulWidget {
#override
_ButtonState createState() => _ButtonState();
}
class _ButtonState extends State<Button> {
var api = Uri.parse('http://192.***.***.***/flutter/teamApi.php');
var response;
var teamApi;
#override
void initState() {
super.initState();
fetchData();
}
fetchData() async {
response = await http.get(api);
print(response.body);
teamApi = jsonDecode(response.body);
setState(() {});
}
#override
Widget build(BuildContext context) {
var color = 0xff453658;
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff392850),
title: Row(
children: [
InkWell(
onTap: () {
Navigator.pop(context);
},
child: Icon(Icons.arrow_back)),
SizedBox(
width: 10.0,
),
Text(
"Income",
style: TextStyle(fontStyle: FontStyle.italic),
),
],
),
actions: [
IconButton(
icon: Icon(Icons.person),
onPressed: () => print("open cart"),
),
],
),
body: Column(
children: [
Container(
margin: const EdgeInsets.all(20.0),
padding: const EdgeInsets.all(10.0),
decoration: BoxDecoration(
border: Border.all(width: 2, color: Color(color))),
child: Row(
children: [
Text(
"Total Income:",
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic),
),
SizedBox(
width: 10.0,
),
Text(
"Rs.2000",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic),
),
],
),
),
SizedBox(
height: 20.0,
),
Flexible(
child: Container(
child: GridView.count(
childAspectRatio: 1.0,
padding: EdgeInsets.only(left: 16, right: 16),
crossAxisCount: 3,
crossAxisSpacing: 18,
mainAxisSpacing: 18,
children: List.generate(
teamApi.length,
(index) => GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
LeftTeam(teamData: teamApi[index])),
);
},
child: Container(
decoration: BoxDecoration(
color: Color(0xff00ffff),
borderRadius: BorderRadius.circular(10)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Text(teamApi[index]["teamType"],
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600)),
),
],
),
),
),
),
),
),
),
],
),
);
}
}
This is API data of button
[{"teamType":"direct team","team_name":"platinum","team_number":"234","team_uniq_id":"1","team_last_update":"10-may-2021"},{"teamType":"left team","team_name":"gold","team_number":"356","team_uniq_id":"2","team_last_update":"10-may-2021"},{"teamType":"right team","team_name":"silver","team_number":"876","team_uniq_id":"3","team_last_update":"10-may-2021"}]
this is code for second file.
this is model part.
class MyData {
List<Results> user = [];
MyData.fromJson(Map<String, dynamic> json) {
// previous = json['previous'];
// next = json['next'];
if (json['results'] != null) {
user = <Results>[];
json['results'].forEach((v) {
user.add(new Results.fromJson(v));
});
}
}
}
class Results {
String user_name = "";
String user_mother_name = "";
String user_address = "";
String user_mobile = "";
String user_sponsor_id = "";
String sponsor_id = "";
String email = "";
String city = "";
String state = "";
String dob = "";
Results.fromJson(Map<String, dynamic> json) {
user_name = json['user_name'];
user_mother_name = json['user_mother_name'];
user_address = json['user_address'];
user_mobile = json['user_mobile'];
user_sponsor_id = json['user_sponsor_id'];
email = json['email'];
city = json['city'];
state = json['state'];
dob = json['dob'];
}
}
this provider of api link.
import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http;
import 'package:practice/LeftTeamFile/model/myData.dart';
class MyHomePageProvider extends ChangeNotifier {
MyData? data;
Future getData(context) async {
var url = Uri.parse(
var url = Uri.parse('http://192.***.***.***/flutter/team_list.php');
var response = await http.get(url);
print("res${response.body}");
var mJson = json.decode(response.body);
this.data = MyData.fromJson(mJson);
this.notifyListeners();
this is teamList part .
import 'package:flutter/material.dart';
import 'package:practice/LeftTeamFile/provider/myHomePageProvider.dart';
import 'package:provider/provider.dart';
class TeamList extends StatefulWidget {
final teamData;
const TeamList({Key? key, this.teamData}) : super(key: key);
#override
_TeamListState createState() => _TeamListState();
}
class _TeamListState extends State<TeamList> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
children: [
Container(
padding: EdgeInsets.all(10.0),
height: 100.0,
color: Color(0xffedbf6b),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(
Icons.list_alt,
color: Colors.white,
),
Text(
widget.teamData['team_uniq_id'],
style: TextStyle(
fontSize: 20.0,
color: Colors.white,
),
),
],
),
]),
),
SizedBox(
height: 10.0,
),
Stack(
children: [
ChangeNotifierProvider<MyHomePageProvider>(
create: (context) => MyHomePageProvider(),
child: Consumer<MyHomePageProvider>(
builder: (context, provider, child) {
if (provider.data!.team_uniq_id ==
widget.teamData['team_uniq_id']) {
print("prov $provider.data");
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
// Data table widget in not scrollable so we have to wrap it in a scroll view when we have a large data set..
child: SingleChildScrollView(
child: DataTable(
columns: [
DataColumn(
label: Text('Name'),
tooltip: 'represents if user is verified.'),
DataColumn(
label: Text('Mother_name'),
tooltip: 'represents first S no of the user'),
DataColumn(
label: Text('address'),
tooltip: 'represents Sponsor ID of the user'),
DataColumn(
label: Text('mobile'),
tooltip: 'represents User ID of the user'),
DataColumn(
label: Text('User_s_id'),
tooltip: 'represents Name of the user'),
DataColumn(
label: Text('sponsor_id'),
tooltip: 'represents Mobile of the user'),
DataColumn(
label: Text('email'),
tooltip: 'represents Date of the user'),
DataColumn(
label: Text('city'),
tooltip: 'represents Date of the user'),
DataColumn(
label: Text('state'),
tooltip: 'represents Date of the user'),
DataColumn(
label: Text('dob'),
tooltip: 'represents Date of the user'),
],
rows: provider.data!.user
.map((data) =>
// we return a DataRow every time
DataRow(
// List<DataCell> cells is required in every row
cells: [
red when unverified
DataCell(Text(data.user_name)),
DataCell(Text(data.user_mother_name)),
DataCell(Text(data.user_address)),
DataCell(Text(data.user_mobile)),
DataCell(Text(data.user_sponsor_id)),
DataCell(Text(data.sponsor_id)),
DataCell(Text(data.email)),
DataCell(Text(data.city)),
DataCell(Text(data.state)),
DataCell(Text(data.dob)),
]))
.toList(),
),
),
);
}, provider.getData(context);
return Center(child: CircularProgressIndicator());
),
),
],
),
],
),
);
}
}
this is teamlist api
[
{
"teamType": "direct Team",
"team_uniq_id": "1",
"user": [
{
"user_name": "deepak",
"user_mother_name": "Accomodation",
"user_address": "varanasi",
"user_mobile": "5678989",
"user_sponsor_id": "123456",
"sponsor_id": "3456",
"email": "abc#gmai.com",
"city": "varanasi",
"state": "India",
"dob": "12-5-1996"
},
{
"user_name": "deepak",
"user_mother_name": "Accomodation",
"user_address": "varanasi",
"user_mobile": "5678989",
"user_sponsor_id": "123456",
"sponsor_id": "3456",
"email": "abc#gmai.com",
"city": "varanasi",
"state": "India",
"dob": "12-5-1996"
},
{
"user_name": "deepak",
"user_mother_name": "Accomodation",
"user_address": "varanasi",
"user_mobile": "5678989",
"user_sponsor_id": "123456",
"sponsor_id": "3456",
"email": "abc#gmai.com",
"city": "varanasi",
"state": "India",
"dob": "12-5-1996"
}
]
},
{
"teamType": "left Team",
"team_uniq_id": "2",
"user": [
{
"user_name": "Ashu",
"user_mother_name": "manju",
"user_address": "Mirzapur",
"user_mobile": "222222",
"user_sponsor_id": "123456",
"sponsor_id": "3456",
"email": "abc#gmai.com",
"city": "varanasi",
"state": "India",
"dob": "12-5-1996"
},
{
"user_name": "Ashutodh",
"user_mother_name": "manju1",
"user_address": "Mirzapur1",
"user_mobile": "2222221",
"user_sponsor_id": "1234561",
"sponsor_id": "34561",
"email": "abc#gmai.com1",
"city": "varanasi1",
"state": "India1",
"dob": "12-5-19961"
}
]
},
{
"teamType": "Right Team",
"team_uniq_id": "3",
"user": [
{
"user_name": "tosh",
"user_mother_name": "snju",
"user_address": "Allahabad",
"user_mobile": "44444444",
"user_sponsor_id": "333456",
"sponsor_id": "6666666",
"email": "jkl#gmai.com",
"city": "lucknow",
"state": "India",
"dob": "15-3-1956"
}
]
},
{
"teamType": "Total Team",
"team_uniq_id": "4",
"user": [
{
"user_name": "tosh",
"user_mother_name": "snju",
"user_address": "Allahabad",
"user_mobile": "44444444",
"user_sponsor_id": "333456",
"sponsor_id": "6666666",
"email": "jkl#gmai.com",
"city": "lucknow",
"state": "India",
"dob": "15-3-1956"
},
{
"user_name": "deepak",
"user_mother_name": "Accomodation",
"user_address": "varanasi",
"user_mobile": "5678989",
"user_sponsor_id": "123456",
"sponsor_id": "3456",
"email": "abc#gmai.com",
"city": "varanasi",
"state": "India",
"dob": "12-5-1996"
},
{
"user_name": "deepak",
"user_mother_name": "Accomodation",
"user_address": "varanasi",
"user_mobile": "5678989",
"user_sponsor_id": "123456",
"sponsor_id": "3456",
"email": "abc#gmai.com",
"city": "varanasi",
"state": "India",
"dob": "12-5-1996"
},
{
"user_name": "tosh",
"user_mother_name": "snju",
"user_address": "Allahabad",
"user_mobile": "44444444",
"user_sponsor_id": "333456",
"sponsor_id": "6666666",
"email": "jkl#gmai.com",
"city": "lucknow",
"state": "India",
"dob": "15-3-1956"
}
]
}
]
I feel some error is coming.
You can try to make sure you convert the object you are getting from the server to list, to be able to pass in the list into the widget

Unable to access the data from the provider

I wish to print the quantity of the items selected but am not able to do so. I am using providers to access data but it's showing some error. The same method worked when I applied it elsewhere but it doesn't seem to work here Please help.
Snippet for the type of data I receive:
{
"delivery_status": true,
"coupon_code": null,
"cart": [
{
"food_item_id": "2c7289c1-17fb-4f3a-90af-7a014e051c53",
"name": "Grape",
"price": 35.0,
"category": "Fresh Fruit Juice",
"available": true,
"veg": false,
"egg": false,
"restaurant": "9adafbd7-a9ba-4890-b707-c9d619c72f02",
"quantity": 1
},
{
"food_item_id": "be303557-90ce-4f9c-a30f-5a6d650977b6",
"name": "Mix Juice",
"price": 35.0,
"category": "Fresh Fruit Juice",
"available": true,
"veg": false,
"egg": false,
"restaurant": "9adafbd7-a9ba-4890-b707-c9d619c72f02",
"quantity": 2
},
{
"food_item_id": "13fb9de8-c774-4f6d-af66-74cc6dedbf14",
"name": "Boondi Raita",
"price": 110.0,
"category": "Salad Bar",
"available": true,
"veg": false,
"egg": false,
"restaurant": "9adafbd7-a9ba-4890-b707-c9d619c72f02",
"quantity": 1
}
],
"total_amount": 215.0
}
Snippet for Mapping Logic:
CartItem _items = CartItem(
couponCode: '',
deliveryStatus: false,
totalAmount: 0.0,
);
CartItem get items {
return _items;
}
// ===============================Looks Here
List<MenuItem> _cartProducts = [];
List<MenuItem> get cartProducts {
return [..._cartProducts];
}
Future<void> getCart() async {
Map<String, String> header = {
'Content-type': 'application/json',
'Authorization': accessToken,
};
try {
final response = await http.get(apiURL + getCartURL, headers: header);
print(response.statusCode);
if (response.statusCode == 200) {
final res = jsonDecode(response.body) as Map<String, dynamic>;
if (res == null) {
return _items;
}
_items = CartItem(
deliveryStatus: res['delivery_status'],
couponCode: res['coupon_code'],
totalAmount: res['total_amount'],
);
// ===============================Looks Here
List<MenuItem> cartStuff = [];
res["cart"].forEach((cartData) {
cartStuff.add(
MenuItem(
foodItemId: cartData['food_item_id'],
category: cartData['category'],
name: cartData['name'],
isAvailable: cartData['available'],
isEgg: cartData['egg'],
isVeg: cartData['veg'],
price: cartData['price'],
restaurant: cartData['restaurant'],
quantity: cartData['quantity'],
),
);
});
// ===============================Looks Here
_cartProducts = cartStuff;
print(_cartProducts);
notifyListeners();
} else if (response.statusCode == 403) {
fetchNewAToken().then((_) {
if (accessToken != null && refreshToken != null) getCart();
notifyListeners();
});
}
} catch (e) {
print("Error in getting the Cart");
print(e);
}
}
Snippet for displaying the data:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../globals/text_styles.dart';
import '../../globals/colors.dart';
import '../../providers/cart.dart';
class QuantityButton extends StatefulWidget {
//The item id received is correct so the error occurs is in accessing the data from the provider.
final itemID;
QuantityButton(this.itemID);
#override
_QuantityButtonState createState() => _QuantityButtonState();
}
class _QuantityButtonState extends State<QuantityButton> {
#override
Widget build(BuildContext context) {
final cartData = Provider.of<Cart>(context);
final cartQty =
cartData.cartProducts.where((item) => item.foodItemId == widget.itemID);
return Container(
width: 100,
height: 40,
child: Card(
color: primaryColor.withOpacity(0.9),
elevation: 0,
shape: RoundedRectangleBorder(
side: BorderSide(color: Colors.black),
borderRadius: BorderRadius.circular(10),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTap: () {
cartData.deleteItems(widget.itemID);
},
child: Icon(
Icons.arrow_left,
color: Colors.white,
size: 25,
),
),
Spacer(),
Container(
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Text(
// =========== Print Quantity Here ===========
'',
style: valueTextStyle,
),
),
),
Spacer(),
GestureDetector(
onTap: () {
cartData.addItems(widget.itemID);
},
child: Icon(
Icons.arrow_right,
color: Colors.white,
size: 25,
),
),
],
),
),
);
}
}

flutter how to update grid view

i have grid view shows all data in list and i have drop down with values like price from low to high and when user select any value then i will re-sort the list at this point all is work correctly and list updated but grid view stell with old list.
i cannot update grid view
class ProductsListState extends State<ProductsList> {
double width;
String _title;
String _selectedSort;
String _language;
ProductsListState(this._title);
List productsList;
int filter;
#override
Widget build(BuildContext context) {
MediaQueryData deviceInfo = MediaQuery.of(context);
width = deviceInfo.size.width;
_language = _language ?? AppLocalizations.of(context).tr('lang');
filter = filter ?? 1;
_selectedSort ??= getSortFilter(_language)[0];
productsList = (productsList ?? getProductsList(filter));
print(productsList);
print(filter);
var size = MediaQuery.of(context).size;
var data = EasyLocalizationProvider.of(context).data;
return EasyLocalizationProvider(
data: data,
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Color.fromRGBO(205, 14, 64, 1),
appBar:
MarketinoAppBar(title: _title, width: width, appContext: context),
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: 13.0,
color: Colors.black.withOpacity(.5),
offset: Offset(6.0, 7.0),
),
],
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20)),
),
),
Column(
children: <Widget>[
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 20, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text('SORT BY: '),
DropdownButton<String>(
value: _selectedSort,
onChanged: (value) {
setState(() {
productsList.sort(
(a, b) => a['price'].compareTo(b['price']));
_selectedSort = value;
filter = 2;
});
},
items: getSortFilter(_language).map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
],
),
),
Container(
child: filter == 1
? Grid(productsList, width, size)
: Grid(getProductsList(2), width, size),
)
],
)
],
),
),
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
EasylocaLizationDelegate(locale: data.locale, path: "assets/language")
],
supportedLocales: [Locale('en', 'US'), Locale('ar', 'SA')],
locale: data.savedLocale,
),
);
}
//replace by json
List getProductsList(int filter) {
List list = [];
list.add({
"id": "1",
"name": "sssss",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "110",
"quantity": "1",
"isLiked": "false",
"max": "5"
});
list.add({
"id": "2",
"name": "sssss",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "112",
"quantity": "1",
"isLiked": "true",
"max": "5"
});
list.add({
"id": "3",
"name": "sssss",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "114",
"quantity": "1",
"isLiked": "true",
"max": "10"
});
list.add({
"id": "4",
"name": "sssssssssssssssssssssssssssssssssssssssssssssssssssssssszzzzz",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "11",
"quantity": "1",
"isLiked": "false",
"max": "1"
});
list.add({
"id": "5",
"name": "sssss",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "110",
"quantity": "1",
"isLiked": "false",
"max": "15"
});
switch (filter) {
case 1:
list.sort((a, b) => a['id'].compareTo(b['id']));
break;
case 2:
list.sort((a, b) => a['price'].compareTo(b['price']));
break;
}
return list;
}
List<String> getSortFilter(String language) {
if (language == 'english')
return [
"الأكثر رواجا",
"السعر من الأقل للأعلى",
"السعر من الأعلى للأقل",
"التخفيضات",
];
else
return [
"Popularty",
"Price: Low to High",
"Price: High to Low",
"Discount",
];
}
}
class Grid extends StatefulWidget {
List productsList;
var _width;
var _size;
Grid(this.productsList, this._width, this._size);
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return GridState(productsList, _width, _size);
}
}
class GridState extends State<Grid> {
List productsList;
var _width;
var _size;
GridState(this.productsList, this._width, this._size);
#override
Widget build(BuildContext context) {
// TODO: implement build
return Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: new GridView.builder(
itemCount: productsList.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: _width > 600 ? 3 : 2,
childAspectRatio: _width > 600 ? 0.6 : _width > 400 ? .725 : .685,
// childAspectRatio: (_itemWidth / _itemHeight),
),
itemBuilder: (BuildContext context, int index) {
return ProductGridTile(
price: double.parse(productsList[index]['price']),
width: _size.width,
image: productsList[index]['imageUrl'],
title: productsList[index]['name'],
likeStatus: productsList[index]['isLiked'] == 'true',
max: double.parse(productsList[index]['max']),
id: int.parse(productsList[index]['id']));
}),
),
);
}
}
gridview updated after re-sort list
You are doing some operations inside the build() method, when you call setState() these operations would be called again. Check that part and also try to update the list this way:
productsList = List.from(productsList)..sort(
(a, b) => a['price'].compareTo(b['price']));