i want to make my LIstTile like checkbox, but the problem is when i click one of them, all of the ofthem is selected.
children: <Widget>[
new Expanded(
child:FutureBuilder<List<Workers>>(
future: fetchWorkers(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? WorkerList(workers: snapshot.data)
: Center(child: CircularProgressIndicator());
},
),),
and here is how i get the value from json and show it to my ListTile
Future<List<Workers>> fetchWorkers(http.Client client) async {
final response = await http.post(app_configuration.getUrl() + 'api/Worker/getAll/');
return compute(parseWorkers, response.body);
}
static List<Workers> parseWorkers(String responseBody) {
final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
return parsed.map<Workers>((json) => Workers.fromJson(json)).toList();
}
and Here is my Workers
class Workers {
final String UserId;
final String Fullname;
Workers(
{
this.UserId,
this.Fullname
});
factory Workers.fromJson(Map<String, dynamic> json) {
return Workers(
UserId: json['UserId'] as String,
Fullname: json['Fullname'] as String,
);
}
}
class WorkerList extends StatefulWidget {
#override
_WorkerListState createState() => new _WorkerListState();
final List<Workers> workers;
WorkerList({Key key, #required this.workers}) : super(key: key);
}
class _WorkerListState extends State<WorkerList> {
var isSelected = false;
var mycolor=Colors.white;
#override
Widget build(BuildContext context) {
return ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: widget.workers.length,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
Card(
child: new ListTile(
selected: isSelected,
leading: const Icon(Icons.info),
title: new Text(widget.workers[index].Fullname),
subtitle: new Text(widget.workers[index].UserId),
onTap: toggleSelection // what should I put here,
),),
],
);
},
);
}
void toggleSelection() {
setState(() {
if (isSelected) {
mycolor=Colors.blue;
isSelected = false;
} else {
mycolor=Colors.grey[300];
isSelected = true;
}
});
}
}
Here is the screenshot
How can i fix it ? did i miss something ?
you can do the following:
add a bool inside your Workers class
class Workers {
final String UserId;
final String Fullname;
bool isSelected=false;//the initializtion is mandatory
Workers(
{
this.UserId,
this.Fullname
});
factory Workers.fromJson(Map<String, dynamic> json) {
return Workers(
UserId: json['UserId'] as String,
Fullname: json['Fullname'] as String,
);
}
}
and in the _WorkerListState fix your ListView like this:
#override
Widget build(BuildContext context) {
return ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: widget.workers.length,
itemBuilder: (context, index) {
return Column(
children: <Widget>[
Card(
child: new ListTile(
selected: widget.workers[index].isSelected,
leading: const Icon(Icons.info),
title: new Text(widget.workers[index].Fullname),
subtitle: new Text(widget.workers[index].UserId),
onTap: (){
//this will select the deselected item
//and will deselect the selected item
setState(() {
widget.workers[index].isSelected != widget.workers[index].isSelected
});
}
),),
],
);
},
);
}
Related
Is there anyway to get a future when displaying a list?
I have list with two user id's ( one of them is the userlogged in, the other one is the user to chat with ).
my goal is to get and display the other users name in the chat.
the issue I am running into, is that you cant do async functions within the list
how can i fix this?
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
var otherUserName = await getOtherUsersName(job.userIdsArr);
;
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
}
}
I tried the following code as suggested but did not work::
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import '../../services/auth/auth_service.dart';
import '../../services/cloud/cloud_chat.dart';
import '../../services/cloud/cloud_storage_constants.dart';
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
}}
The simple and short answer is to use FutureBuilder which take future as named parameter and give you the result in builders parameters generally know as snapshot.
First of all wrap your list view with future builder :
FutureBuilder(
future: "you future funtion here",
builder: (context, snapshot) {
return ListView.builder(itemBuilder: itemBuilder);
}
)
now you can give future funtion , in your case it is
FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
And remember to use snapshot if conditions for loading and empty data
complete code
import 'package:flutter/material.dart';
typedef JobCallback = void Function(CloudChat job);
class ChatsListWidget extends StatelessWidget {
final Iterable<CloudChat> cloudChats; // list of jobs
final JobCallback onDeleteJob;
final JobCallback onTap;
String get userId => AuthService.firebase().currentUser!.id;
const ChatsListWidget({
Key? key,
required this.cloudChats,
required this.onDeleteJob,
required this.onTap,
}) : super(key: key);
Future getOtherUsersName(userIdsArr) async {
String? otherUserInChatId;
for (var _userId in userIdsArr) {
if (_userId != userId) {
otherUserInChatId = _userId;
}
}
var userData = await FirebaseFirestore.instance
.collection('user')
.doc(otherUserInChatId)
.get();
return userData[userFirstNameColumn];
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getOtherUsersName(job.userIdsArr),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: cloudChats.length,
itemBuilder: (context, index) {
final job = cloudChats.elementAt(index);
return ListTile(
onTap: () {
onTap(job);
},
title: Text(
otherUserName,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
//
},
icon: const Icon(Icons.delete),
),
);
},
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
Center(
child: CircularProgressIndicator(),
);
}
return Center(
child: Text("Empty"),
);
},
);
}}
HopeFully It will help you.
I am trying to load a listview using flutter and dart but am having an issue, bare with me am new to flutter and learning by example https://github.com/didinj/flutter-crud-restapi-example/blob/master/lib/caseslist.dart am coming from a c# background. I obfuscated my api url to protect it it is valid my side.
class PlayerList extends StatelessWidget {
final List<Player> players;
PlayerList({Key key, this.players}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: players == null ? 0 : players.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: InkWell(
onTap: () {},
child: ListTile(
leading: Icon(Icons.person),
title: Text(players[index].firstName),
subtitle: Text(players[index].surname.toString()),
),
));
});
}
}
The issue surrounds this line.
PlayerList({Key key, this.players}) : super(key: key);
It says key does not exist.
I am loading the list view as such?.
#override
Widget build(BuildContext context) {
if (players == null) {
players = api.getAllPlayers() as List<Player>;
}
return Scaffold(
appBar: AppBar(
title: const Text("Flutter ListView"),
),
drawer: Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: new Center(
child: new FutureBuilder(
future: loadList(),
builder: (context, snapshot) {
return players.length > 0
? new PlayerList(players: players)
: new Center(
child: new Text('No data found, tap plus button to add!',
style: Theme.of(context).textTheme.titleLarge));
},
)),
));
}
Future loadList() {
Future<List<Player>> playersApi = api.getAllPlayers();
playersApi.then((PlayerList) {
setState(() {
this.players = PlayerList;
});
});
return playersApi;
}
}
My Api Call is
class ApiService {
final String apiUrl = "https://secreturl/api";
final String getAllPlayersEndPoint = "/GetAllPlayers/";
Future<List<Player>> getAllPlayers() async {
final getallPlayersUrl = Uri.parse(apiUrl + getAllPlayersEndPoint);
Response res = await get(getallPlayersUrl);
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Player> players =
body.map((dynamic item) => Player.fromJson(item)).toList();
return players;
} else {
throw "Failed to load cases list";
}
}
}
This is my Model
class Player {
final int id;
final int type;
final String playerLevel;
final String firstName;
final String surname;
Player(this.id, this.type, this.playerLevel, this.firstName, this.surname);
factory Player.fromJson(Map<String, dynamic> json) {
return Player(
json['id'],
json['type'],
json['playerlevel'],
json['firstname'],
json['surname'],
);
}
#override
String toString() =>
'Players{id: $id, firstName: $firstName, lastName: $surname}';
}
Hello guys I face this problem when I Create a Search Delegate in a flutter
I try to call data from Firebase and add it in List Class but it shows me this error
List<dynamic> is not a subtype fo type List<Itemshop> of function result
Problem Here
List<ItemShop> ItemShopList = [];
CollectionReference ItemShopRef =
FirebaseFirestore.instance.collection('ItemShop');
List filterItemShop = [];
int counter = 0;
Future getData() async {
var responsce = await ItemShopRef.get();
responsce.docs.forEach((element) {
ItemShop itemShop = ItemShop(element["ItemCatgore"], element["ItemImage"],
element["ItemKG"], element['ItemName'], element["ItemPrice"]);
if (counter == 0) {
ItemShopList.add(itemShop);
}
});
print(ItemShopList);
return ItemShopList;
}
Class for ItemShop
class ItemShop {
final String ItemCatgore, ItemImage, ItemKG, ItemName;
int ItemPrice;
ItemShop(this.ItemCatgore, this.ItemImage, this.ItemKG, this.ItemName,
this.ItemPrice);
}
Full Code:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class SearchPage extends StatefulWidget {
const SearchPage({Key? key}) : super(key: key);
#override
State<SearchPage> createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 184, 132, 132),
actions: [
IconButton(
onPressed: () {
showSearch(context: context, delegate: mySearch());
},
icon: Icon(Icons.search))
],
),
);
}
}
class mySearch extends SearchDelegate {
List<ItemShop> ItemShopList = [];
CollectionReference ItemShopRef =
FirebaseFirestore.instance.collection('ItemShop');
List filterItemShop = [];
int counter = 0;
Future getData() async {
var responsce = await ItemShopRef.get();
responsce.docs.forEach((element) {
ItemShop itemShop = ItemShop(element["ItemCatgore"], element["ItemImage"],
element["ItemKG"], element['ItemName'], element["ItemPrice"]);
if (counter == 0) {
ItemShopList.add(itemShop);
}
});
print(ItemShopList);
return ItemShopList;
}
////////////////////////////////////////////////
#override
List<Widget>? buildActions(BuildContext context) {
return [
IconButton(
onPressed: () {
query = "";
},
icon: Icon(Icons.close))
];
}
#override
Widget? buildLeading(BuildContext context) {
return IconButton(
onPressed: () {
close(context, null);
},
icon: Icon(Icons.arrow_back));
}
#override
Widget buildResults(BuildContext context) {
return FutureBuilder(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int i) {
return snapshot.data[i].ItemName == query
? Card(
child: Column(
children: [
Container(
color: Colors.grey[200],
height: 150,
width: double.infinity,
child: Text(
snapshot.data[i].ItemName,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 35),
),
),
Container(
child: Text(snapshot.data[i].ItemName),
)
],
),
)
: Container();
});
}
});
}
#override
Widget buildSuggestions(BuildContext context) {
filterItemShop = ItemShopList.where((element) =>
element.ItemName.toLowerCase().contains(query.toLowerCase())).toList();
return FutureBuilder(
future: getData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return ListView.builder(
itemCount:
query == "" ? snapshot.data.length : filterItemShop.length,
itemBuilder: (BuildContext context, int i) {
return InkWell(
onTap: () {
query = query == ""
? ItemShopList[i].ItemName
: filterItemShop[i].ItemName;
showResults(context);
},
child: Card(
child: query == ""
? ListTile(
leading: Text(snapshot.data[i].ItemName),
title: Text(snapshot.data[i].ItemName),
subtitle: Text(snapshot.data[i].ItemName),
)
: ListTile(
leading: Text(filterItemShop[i].ItemName),
title: Text(filterItemShop[i].ItemName),
subtitle: Text(filterItemShop[i].ItemName),
),
),
);
});
}
});
}
}
class ItemShop {
final String ItemCatgore, ItemImage, ItemKG, ItemName;
int ItemPrice;
ItemShop(this.ItemCatgore, this.ItemImage, this.ItemKG, this.ItemName,
this.ItemPrice);
}
there, I think the better approach is not for each but map. and use type defines variable so you will not get type error as long as you do not use casting method. final List<Itemshop> x = responsce.docs.map((e)=>Itemshop.fromMap(e.data()..docId = e.id)).toList(); return x;
ypu can also just retun the map fucntion like return responsce.docs.map((e)=> ....
Itemshop should be ItemShop, standard dart format.
Itemshop.fromMap is a function that you build in Itemshop class. data classes always have this kind of helper. fromMap, toMap, fromJson, toJson. a lot of code generation in the dart for this if you don't want to write it yourself.
For example for your comment,
import 'dart:convert';
class ItemShop {
final String? itemCatgore;
final String? itemImage;
final String? ItemKG;
final String? ItemName;
final String? ItemPrice;
ItemShop({
this.itemCatgore,
this.itemImage,
this.ItemKG,
this.ItemName,
this.ItemPrice,
});
Map<String, dynamic> toMap() {
return {
'itemCatgore': itemCatgore,
'itemImage': itemImage,
'ItemKG': ItemKG,
'ItemName': ItemName,
'ItemPrice': ItemPrice,
};
}
factory ItemShop.fromMap(Map<String, dynamic> map) {
return ItemShop(
itemCatgore: map['itemCatgore'],
itemImage: map['itemImage'],
ItemKG: map['ItemKG'],
ItemName: map['ItemName'],
ItemPrice: map['ItemPrice'],
);
}
String toJson() => json.encode(toMap());
factory ItemShop.fromJson(String source) =>
ItemShop.fromMap(json.decode(source));
ItemShop copyWith({
String? itemCatgore,
String? itemImage,
String? ItemKG,
String? ItemName,
String? ItemPrice,
}) {
return ItemShop(
itemCatgore: itemCatgore ?? this.itemCatgore,
itemImage: itemImage ?? this.itemImage,
ItemKG: ItemKG ?? this.ItemKG,
ItemName: ItemName ?? this.ItemName,
ItemPrice: ItemPrice ?? this.ItemPrice,
);
}
#override
String toString() {
return 'ItemShop(itemCatgore: $itemCatgore, itemImage: $itemImage, ItemKG: $ItemKG, ItemName: $ItemName, ItemPrice: $ItemPrice)';
}
#override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ItemShop &&
other.itemCatgore == itemCatgore &&
other.itemImage == itemImage &&
other.ItemKG == ItemKG &&
other.ItemName == ItemName &&
other.ItemPrice == ItemPrice;
}
#override
int get hashCode {
return itemCatgore.hashCode ^
itemImage.hashCode ^
ItemKG.hashCode ^
ItemName.hashCode ^
ItemPrice.hashCode;
}
}
plus dart use camel case for all the variable and function (first latest is small later, second-word first letter is capital)
and all words first capital letter
Specify the type of future in futurebuilder, here it is list itemshop as shown below.
return FutureBuilder<List<ItemShop>>(
//TODO: YOUR CODE
);
I want to increment number on trailing ListTile Flutter when ontap ListTile,
but always return to 0?
i'm using future builder fyi,
thanks in advance
this my model
class ItemModel {
String name;
String price;
String image;
bool isSelected = false;
int countSelected = 0;
ItemModel(
this.name,
this.price,
this.image,
);
}
This method to get data from api json from local server
Future<List<ItemModel>> _getItems() async {
List<ItemModel> listItems = [];
var url = Uri.parse(BASEURLLOCAL.apiGetItems);
var data = await http.get(url);
var jsonData = jsonDecode(data.body);
for (var p in jsonData) {
ItemModel item = ItemModel(
p["name"],
p["price"],
p["image"],
// p["PRODUCT_NAME"],
// p["PRICE_SELL"],
// p["FILENAME"],
);
listItems.add(item);
}
return listItems;
}
and this the listview builder
#override
Widget build(BuildContext context) {
return FutureBuilder<List<ItemModel>>(
future: _getItems(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
} else {
return ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext contex, int idx) {
if (_itemCount.length < snapshot.data.length) {
_itemCount.add(0);
}
return Card(
child: ListTile(
leading: Image.network(
BASEURLLOCAL.imgItem + snapshot.data[idx].image),
title: Text(snapshot.data[idx].name),
subtitle: Text(snapshot.data[idx].price),
// trailing: _buildTrailing(),
trailing: Text(snapshot.data[idx].countSelected.toString()),
onTap: () {
setState(() {
snapshot.data[idx].countSelected++;
});
},
),
);
},
);
}
},
);
}
this is what the problem is
Try something like this, create a list
List<ItemModel> listItems = [];
then, in initState() call the _getItems()
_getItems() async {
var url = Uri.parse(BASEURLLOCAL.apiGetItems);
var data = await http.get(url);
var jsonData = jsonDecode(data.body);
for (var p in jsonData) {
ItemModel item = ItemModel(
p["name"],
p["price"],
p["image"],
// p["PRODUCT_NAME"],
// p["PRICE_SELL"],
// p["FILENAME"],
);
listItems.add(item);
}
}
And remove FutureBuilder
#override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
itemCount: listItems.length,
itemBuilder: (BuildContext context, int idx) {
if (_itemCount.length < listItems.length) {
_itemCount.add(0);
}
return Card(
child: ListTile(
leading: Image.network(BASEURLLOCAL.imgItem + listItems[idx].image),
title: Text(listItems[idx].name),
subtitle: Text(listItems[idx].price),
// trailing: _buildTrailing(),
trailing: Text(listItems[idx].countSelected.toString()),
onTap: () {
setState(() {
listItems[idx].countSelected++;
});
},
),
);
},
);
}
By this way it won't fetch everytime when it rebuilds.
I'm new in flutter, I'd like to know how to add an item list dynamically to ListView without reloading data in FutureBuilder.
When I add an item to the ListView, it duplicate the list and then added the item to that list.
The Following code, include Model clas called Job.
JobListView is a stateful widget that include the dynamic ListView.
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
class Job {
#required
String company;
String description;
String employmentType;
int id;
String location;
String position;
List<String> skillsRequired;
Job(
this.company,
this.description,
this.employmentType,
this.id,
this.location,
this.position,
this.skillsRequired);
Job.fromJson(Map<String, dynamic> json) {
company = json['company'];
description = json['description'];
employmentType = json['employmentType'];
id = json['id'];
location = json['location'];
position = json['position'];
if (json['skillsRequired'] != null) {
skillsRequired = new List<String>();
json['skillsRequired'].forEach((v) {
skillsRequired.add(v);
});
}
}
}
class JobListView extends StatefulWidget {
#override
_JobListViewState createState() => _JobListViewState();
}
class _JobListViewState extends State<JobListView> {
List<Job> data = List<Job>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Job>>(
future: _getJob(),
builder: (context, snapshot) {
if (snapshot.hasData) {
data = snapshot.data;
return _listViewFormat(data);
} else if (snapshot.hasError) {
return Container();
}
return Center(
child: Container(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
);
},
) ,
floatingActionButton: (FloatingActionButton(child: Icon(Icons.add),onPressed: (){
setState(() {
var j = Job("CompanyX","Eng.5 position","Full-time",0,"Cairo","Senior",null);
data.add(j);
});
},)),
);
}
}
ListView _listViewFormat(List<Job> data) {
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return _tile(data[index].position, data[index].description, Icons.work);
});
}
ListTile _tile(String title, String subtitle, IconData iconData) {
return ListTile(
title: Text(title, style: TextStyle(fontSize: 20)),
subtitle: Text(
subtitle,
style: TextStyle(fontSize: 12),
),
leading: Icon(iconData),
trailing: Icon(Icons.arrow_right),
);
}
Future<List<Job>> _getJob() async {
String baseUrl = 'https://mock-json-service.glitch.me';
var response = await get(baseUrl);
if (response.statusCode == 200) {
List jsonResponse = json.decode(response.body);
return jsonResponse.map((job) => new Job.fromJson(job)).toList();
}
}
Check out this more explanation How to deal with unwanted widget build?
if future changes you will see changes
Move _getJob method inside initState like this:
class _JobListViewState extends State<JobListView> {
List<Job> data = List<Job>();
Future<List<Job>> getJobFuture;
#override
void initState() {
super.initState();
getJobFuture = _getJob();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder<List<Job>>(
future: getJobFuture,
builder: (context, snapshot) {
if (snapshot.hasData) {
data = snapshot.data;
return _listViewFormat(data);
} else if (snapshot.hasError) {
return Container();
}
return Center(
child: Container(
width: 50,
height: 50,
child: CircularProgressIndicator(),
),
);
},
) ,
floatingActionButton: (FloatingActionButton(child: Icon(Icons.add),onPressed: (){
setState(() {
var j = Job("CompanyX","Eng.5 position","Full-time",0,"Cairo","Senior",null);
data.add(j);
});
},)),
);
}
}