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

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

Related

how to check value in list empty or not and if not get the value

I am getting a list from servers like this
[
{
"Date": "2022-10-21",
"Wages": [
{
"Name": "101 Working hours",
"Balance": "8.00",
"Date": "2022-10-21",
"ShiftName": "AU128"
},
{
"Name": "102 Bonus pay",
"Balance": "3:48",
"Date": "2022-10-21",
"ShiftName": ""
},
{
"Name": "110 Split Shift",
"Balance": "1:00",
"Date": "2022-10-21",
"ShiftName": ""
},
{
"Name": "111 Wage reduction",
"Balance": "1:00",
"Date": "2022-10-21",
"ShiftName": ""
}
]
},
]
I want to get ShiftName if it is not empty and shows at FE. shift name is in Wages List
Text(
Wages[i].shiftName ?? "",
style: wageTextStyle,
),
I try to use List.any((any) => any.containsValue());
but I do not know which value I get from server because shiftName can be changed
my API calling method from provider Consumer
Consumer<EmployeeWageAccountsProvider>(
builder: (context, data, child) {
if (!data.isLoading) {
int length = data.getEmployeeAccountsData!.length;
if (data.getEmployeeAccountsData!.isNotEmpty) {
wageAccountsData = data.getEmployeeAccountsData!;
return ListView.builder(
itemCount: length,
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemBuilder: (context, i) {
return WageAccountsCard(
date: Helper.formatStringDate(
wageAccountsData[i].date!),
shiftName: wageAccountsData[i].wages!
[i].shiftName!.isEmpty ? "":wageAccountsData[i].wages!
[i].shiftName,
wages: wageAccountsData[i].wages,
);
},
);
}
return noDataFound(context, 50);
}
return const WageAccountsShimmer();
}),
wage accounts card to displaying data to user
class WageAccountsCard extends StatelessWidget {
final String? date;
final String? shiftName;
final List<Wages>? wages;
const WageAccountsCard(
{Key? key,
this.date,
this.shiftName,
this.wages})
: super(key: key);
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.all(10),
padding: const EdgeInsets.all(8),
decoration: CustomBoxDecoration.cardDecoration(context,
shadow: true),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
shiftName ?? "",
style: wageTextStyle,
),
Text(
date.toString(),
style: wageTextStyle,
),
],
),
SizedBox(
height: Styles.height(context) * 0.01,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
S.of(context).wage_type,
style: cTextStyle,
),
Text(
S.of(context).balance,
style: cTextStyle,
),
],
),
const Divider(
color: Colors.black,
),
]
),
);
}
}
shiftName ?? "", used to return default value on null case.
You are getting empty String, therefore you can do
shiftName.isEmpty ? "onEmptyCaseValue" : shiftName
return shiftName.isEmpty ? Center(child: Text('Empty')) : Text(
shiftName ?? "",
style: wageTextStyle,
),
wageAccountsData[i].wages!
[i].shiftName!.isEmpty ? "":wageAccountsData[i].wages[i].shiftName,
insted of this just write like this
wageAccountsData[i].wages![i].shiftName ?? "Default Text",

How to load a list of AudioSource from GraphQL API in 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

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

Convert data from an API to lists and use it in dependent Dropdownbuttons

I want to convert this API to multiable lists
it should act like the image below
https://i.stack.imgur.com/10Qld.png
Any help will be appreciated
I want to convert
1-categories.name toList
2-categories.children.name toList
3-categories.children.children_lv.name toList
4-categories.children.name.children_lv.children.name toList
and want to make every dropdown dependant to the previous one
Example:
the user should select from categories.name toList to be able to choose from 2-categories.children.name toList
API
"categories": [
{
"category_id": "1841",
"name": "Cars",
"children": [
{
"name": "Car1",
"category_id": "1845",
"children_lv": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
"column": "1",
{
"name": "Car2",
"category_id": "1846",
"children_lv": [
{
"name": "Car2_1",
"category_id": "1847",
"children_lv": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
},
{
"name": "Car2_2",
"category_id": "1848",
"children_lv": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
}
],
}
],
},
{
"category_id": "1842",
"name": "Properties",
"children": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
"column": "1",
},
{
"category_id": "1843",
"name": "Machines",
"children": [
{
"name": "",
"category_id": "",
"children_lv": "",
}
],
"column": "1",
},
{
"category_id": "1844",
"name": "Electronics",
"children": [
{
"name": "",
"category_id": "",
"children_lv": "",
"href": ""
}
],
"column": "1",
}
]
}```
the lists that should be converted are category, children and the other children_lv
**Model has been made with app.quicktype.io and it works **
List<T> list = (map['list'] as List).map<T>((e)=>T.fromMap(e));
Try with this, but replace T with Model.
Also it should have fromMap function, to parse Map<String,dynamic> to your model.
else use normal constructors
((e)=>T(a:e['a'], b:e['b']);
Here is an example:
class Model {
final String a;
final String b;
Model({this.a,this.b});
factory Model.fromMap(Map<String,dynamic> map) =>
Model(
a: map['a'],
b: map['b']
);
}
This is a model with fromMap function. You can get that function easy with plugins for AndroidStudio or VSCode.
The one I use for android studio is called DartDataClass.
Now when you have json with lists =>
{ list : [
{ "a":"we","b":"try"},
{ "a":"as","b":"dfg"},
]}
You can use code above to parse that JSON if you have create the model for it.
Map<String,dynamic> json = jsonDecode(jsonSource);
List<Model> list = (json['list'] as List).map<Model>((e)=>Model.fromMap(e)).toList();
I did an example, the same as your example, but changed some names to make it clear to you
First, you need to create the Classes that you need like this:
Example of only one class ***** the same thing applies to the other classes *****
myCategory.dart
import 'package:flutterapp/myCategory1.dart';
import 'package:json_annotation/json_annotation.dart';
part 'myCategory.g.dart';
#JsonSerializable()
class MyCategory {
String name;
List<MyCategory1> children1;
MyCategory({this.name,this.children1});
factory MyCategory.fromJson(Map<String, dynamic> json) =>
_$MyCategoryFromJson(json);
Map<String, dynamic> toJson() => _$MyCategoryToJson(this);
}
myCategory.g.dart
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'myCategory.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
MyCategory _$MyCategoryFromJson(Map<String, dynamic> json) {
return MyCategory(
name: json['name'] as String,
children1: (json['children1'] as List)
?.map((e) => e == null
? null
: MyCategory1.fromJson(e as Map<String, dynamic>))
?.toList());
}
Map<String, dynamic> _$MyCategoryToJson(MyCategory instance) =>
<String, dynamic>{'name': instance.name, 'children1': instance.children1};
the myCategory.g.dart is generic file by json_serializable,
pubspec.yaml
dependencies:
flutter:
sdk: flutter
json_serializable: ^3.4.1
dev_dependencies:
build_runner: ^1.10.0
Where I generate it with the following command
flutter pub run build_runner build --delete-conflicting-outputs
Of course, you can use another method, but I prefer this method
Now let's take a look at the most important thing:
class CategoriesWidget extends StatefulWidget {
#override
_CategoriesWidgetState createState() => new _CategoriesWidgetState();
}
class _CategoriesWidgetState extends State<CategoriesWidget> {
List<MyCategory> myNestedList;
MyCategory _selectedMyCategory;
MyCategory1 _selectedMyCategory1;
MyCategory2 _selectedMyCategory2;
#override
void initState() {
super.initState();
myNestedList =
(map['categories'] as List).map((e) => MyCategory.fromJson(e)).toList();
}
Map<String, dynamic> map = {
'categories': [
{
"name": '1',
"children1": [
{"name": '1-1'},
{
"name": '1-2',
'children2': [
{'name': '1-2-1'},
{'name': '1-2-2'}
]
}
]
},
{
"name": '2',
"children1": [
{"name": '2-1'},
{
"name": '2-2',
'children2': [
{'name': '2-2-1'},
{'name': '2-2-2'}
]
}
]
}
]
};
#override
Widget build(BuildContext context) {
return Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
appBar: AppBar(
title: Text("Dropdown Categories"),
centerTitle: true,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey, width: 0.5)),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 8),
margin: EdgeInsets.all(8),
child: DropdownButton(
isDense: true,
isExpanded: true,
hint: Text('My categories'),
underline: Container(),
items: myNestedList.map((item) {
return DropdownMenuItem(
value: item,
child: Text(item.name),
);
}).toList(),
value: _selectedMyCategory,
onChanged: (value) {
setState(() {
_selectedMyCategory = value;
if (_selectedMyCategory1 != null) {
_selectedMyCategory1 = _selectedMyCategory.children1
.firstWhere(
(element) => element == _selectedMyCategory1,
orElse: () => null);
}
});
},
),
),
_selectedMyCategory?.children1 != null &&
_selectedMyCategory.children1.length > 0
? Container(
height: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey, width: 0.5)),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 8),
margin: EdgeInsets.all(8),
child: DropdownButton(
isDense: true,
isExpanded: true,
hint: Text('My categories 1'),
underline: Container(),
value: _selectedMyCategory1,
items: _selectedMyCategory.children1.map((item) {
return DropdownMenuItem(
value: item,
child: Text(item.name),
);
}).toList(),
onChanged: (value) {
setState(() {
_selectedMyCategory1 = value;
if (_selectedMyCategory2 != null) {
_selectedMyCategory2 =
_selectedMyCategory1.children2.firstWhere(
(element) =>
element == _selectedMyCategory2,
orElse: () => null);
}
});
},
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text('My categories 1')),
),
_selectedMyCategory1?.children2 != null &&
_selectedMyCategory1.children2.length > 0
? Container(
height: 45,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.grey, width: 0.5)),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 8),
margin: EdgeInsets.all(8),
child: DropdownButton(
isDense: true,
isExpanded: true,
hint: Text('My categories 2'),
underline: Container(),
items: _selectedMyCategory1.children2.map((item) {
return DropdownMenuItem(
value: item,
child: Text(item.name),
);
}).toList(),
value: _selectedMyCategory2,
onChanged: (value) {
setState(() {
_selectedMyCategory2 = value;
});
},
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text('My categories 2')),
),
],
),
),
);
}
}
I tried it myself, and here is the result:
Good luck

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']));