I have trouble displaying data, all data is received correctly from Get method, but I can not handle it to show values.
in the getDataLadder successfully received data in response.body and i can see result with print('Response Body : ${response.body}');
with this section i store data in stringResponse value , but i can't show json data in this section:
Widget getBody() {
var size = MediaQuery.of(context).size;
return Container(
width: size.width,
height: size.height,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10)),
color: Colors.white),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Container(
height: 1,
decoration:
BoxDecoration(color: Colors.grey.withOpacity(0.2)),
),
),
SizedBox(
width: 10,
),
Text(
stringResponse.toString(),
style: TextStyle(color: Colors.black54),
),
SizedBox(
width: 10,
),
Flexible(
child: Container(
height: 1,
decoration:
BoxDecoration(color: Colors.grey.withOpacity(0.2)),
),
),
],
),
SizedBox(
height: 15,
),
Column(
children: List.generate(nardeban_data.length, (index) {
return Column(
children: [
Padding(
padding: const EdgeInsets.only(right: 5, left: 5),
child: Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/images/bg.png"),
fit: BoxFit.fill,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: 90,
// width: (size.width - 20) * 0.68,
child: Row(
children: [
SizedBox(width: 20), // give it width
Container(
width: 40,
decoration: BoxDecoration(
color: Colors.blue,
border:
Border.all(color: Colors.blue),
borderRadius:
BorderRadius.circular(40.0)),
child: Padding(
padding: EdgeInsets.all(10.0),
child: Text("14",
style: TextStyle(
fontSize: 13.0,
fontWeight: FontWeight.bold,
color: Colors.white)))),
SizedBox(
width: 10,
),
Container(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
nardeban_data[index]['name'],
style: TextStyle(
fontSize: 14,
color: Colors.black54,
fontWeight: FontWeight.w400),
overflow: TextOverflow.ellipsis,
),
],
),
)
],
),
),
Container(
width: (size.width - 120) * 0.32,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue)),
child: Padding(
padding: const EdgeInsets.only(
right: 10,
bottom: 4,
left: 10,
top: 4),
child: Row(
children: [
SizedBox(
width: 25,
height: 25,
child: TextField(
textAlign: TextAlign.center,
keyboardType:
TextInputType.number,
decoration: InputDecoration(
hintText: '4%',
border: InputBorder.none,
contentPadding: EdgeInsets.only(
bottom: 8,
top: 3,
),
),
),
)
],
),
),
),
// Icon(
// Icons.notifications,
// size: 22,
// color: Colors.blue.withOpacity(0.7),
// )
],
),
)
],
),
)),
],
);
})),
],
),
),
);
}
this is my json style when i get from api:
{
"pellekan": [
{
"name": "1",
"form": null,
"to": "1000000",
"percent": 1
},
{
"name": "2",
"form": "1000000",
"to": 1100000,
"percent": 2.89
},
{
"name": "3",
"form": "1000000",
"to": 1200000,
"percent": 4.79
},
]
}
also this is my class and i difine stringResponse value out of that
var stringResponse = [];
class ResultLadder extends StatefulWidget implements PreferredSizeWidget {
#override
Size get preferredSize => const Size.fromHeight(100);
const ResultLadder({Key? key}) : super(key: key);
#override
_ResultLadderState createState() => _ResultLadderState();
}
Future<String> getToken() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('login')!;
}
class _ResultLadderState extends State<ResultLadder> {
String token = "";
#override
void initState() {
// getInfo();
getDataLadder();
super.initState();
}
generally, for example how i can show name in json data instead of "14" , in this below:code:
child: Text("14",
style: TextStyle(
fontSize: 13.0,
fontWeight: FontWeight.bold,
color: Colors.white))
this is getDataLadder Code :
Future getDataLadder() async {
print('bye');
String token = await getToken();
var response = await http.get(
Uri.parse('https://mylocalapiurl.com/backend/api/v1/pellekan/main/active'),
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
});
print('Token : ${token}');
print('Response Body : ${response.body}');
if (response.statusCode == 200) {
setState(() {
stringResponse = json.decode(response.body);
});
}
}
nardeban ladder is one file in data folder and i add this values for show data demo (this is working):
const List nardeban_data = [
{
"img":
"https://images.unsplash.com/image.jpg",
"name": "mark wiliams",
"takhfif": "description item"
},
{
"img":
"https://images.unsplash.com/photo-1610859923380-c8e5a13165d1?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=1000&q=80",
"name": "joe mark",
"takhfif": "description item"
},
];```
So now use your stringResponse since it has already been decoded into JSON, I'd create a small PODO (Plain Ol' Dart Object) to map my JSON to the data you're receiving, as in:
class NardebanData {
String? name;
String? form;
String? to;
double? percent;
NardebanData({ this.name, this.form, this.to, this.percent });
factory NardebanData.fromJson(Map<String, dynamic> json) {
return NardebanData(
name: json['name'],
form: json['form'],
to: json['to'],
percent: json['percent']
);
}
}
Inside your setState() call, then map it as such:
setState(() {
stringResponse = json.decode(response.body);
nardeban_data = (stringResponse['pellekan'] as List<dynamic>).map((d) => NardebanData.fromJson(d)).toList();
});
So make your nardeban_data not a const anymore, but a List of NardebanData objects:
List<NardebanData> narbeban_data = [];
And when you consume it (inside of your List.generate) you could fetch the current object in the iteration, as in:
children: List.generate(nardeban_data.length, (index) {
// fetch the item in the collection by the index provided
NardebanData dataItem = nardeban_data[index];
// ALL YOUR WIDGET STRUCTURE HERE
// LIKE YOUR TEXT WIDGETS AS IN:
Text(
dataItem.name!, // pull the data out of the dataItem using the provided properties
style: TextStyle(
fontSize: 14,
color: Colors.black54,
fontWeight: FontWeight.w400),
overflow: TextOverflow.ellipsis,
),
}
Also make sure your JSON data coming from your API is consistent as far as the type of data in each field, otherwise the decoding will fail (i.e. make sure that name, form, to are Strings, and percent is a double).
See if that works for you.
Related
I am trying to load an image from Firebase Firestore in a Flutter app, but I am getting the following error message:
RangeError (index): Invalid value: Valid value range is empty: 0
,
model.thumbnailUrl[0] is where the error is coming
Here is the relevant code for the CategoryProductCard class where I'm trying to display the image:
import 'package:flutter/material.dart';
import 'package:user/Config/method.dart';
import 'package:user/model/item.dart';
import 'package:user/screens/product_page.dart';
import 'package:user/widgets/customTextWidget.dart';
class CategoryProductCard extends StatelessWidget {
final ItemModel model;
CategoryProductCard({this.model});
#override
Widget build(BuildContext context) {
// double discount1 = ((model.mrp.toDouble() - model.price.toDouble()) /
// model.mrp.toDouble()) *
// 100.0;
// int discount = discount1.toInt().ceil();
final size = MediaQuery.of(context).size;
return Container(
color: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 0),
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(left: 0.0, top: 0),
child: Stack(
children: [
Container(
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(5)),
height: 250,
width: size.width * .48,
child: InkWell(
onTap: () {
Route route = MaterialPageRoute(
builder: (_) => ProductPage(itemModel: model));
Navigator.push(context, route);
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5),
topRight: Radius.circular(5)),
child: Image.network(
model.thumbnailUrl[0],
height: 150,
width: size.width * .48,
fit: BoxFit.fill,
),
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
SizedBox(
width: 5,
),
Padding(
padding: const EdgeInsets.only(
left: 5.0, right: 5, top: 8),
child: Text(
model.title,
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
fontSize: 14,
),
),
// child: CustomText(
// overflow: TextOverflow.ellipsis,
// text: model.title,
// size: 15,
// fontWeight: FontWeight.w600,
// ),
),
// RichText(
// text: new TextSpan(
// children: <TextSpan>[
// new TextSpan(
// text: 'MRP: ₹${model.price}',
// style: new TextStyle(
// color: Colors.grey[500],
// fontSize: 12,
// decoration: TextDecoration.lineThrough,
// ),
// ),
// ],
// ),
// ),
Padding(
padding: const EdgeInsets.only(top: 5, bottom: 5),
child: RichText(
text: new TextSpan(
children: <TextSpan>[
new TextSpan(
text: 'MRP: ₹${model.mrp}',
style: new TextStyle(
color: Colors.grey[500],
fontSize: 11,
decoration: TextDecoration.lineThrough,
),
),
],
),
),
),
RichText(
text: new TextSpan(
children: <TextSpan>[
new TextSpan(
text: 'Price: ',
style: new TextStyle(
fontSize: 12,
fontWeight: FontWeight.normal,
color: Colors.black87,
),
),
new TextSpan(
text: '₹ ${model.price}',
style: new TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: Theme.of(context).primaryColor,
),
),
],
),
),
// Padding(
// padding: const EdgeInsets.only(left: 5.0, top: 0),
// child: CustomText(
// overflow: TextOverflow.ellipsis,
// text: model.longDescription,
// size: 12,
// )),
SizedBox(
height: 12,
),
],
),
// Padding(
// padding: const EdgeInsets.symmetric(horizontal: 5.0),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// CustomText(
// text: '₹' + (model.price).toString(),
// color: Theme.of(context).primaryColor,
// size: 14,
// fontWeight: FontWeight.w500,
// ),
// Container(
// alignment: Alignment.center,
// height: 20,
// width: 60,
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(5),
// color: Colors.red.withOpacity(.1)),
// child: CustomText(
// text: '₹' +
// (model.discount).toString() +
// ' Off',
// color: Theme.of(context).primaryColor,
// size: 12,
// fontWeight: FontWeight.normal,
// ),
// ),
// ],
// ),
// )
],
),
),
),
Positioned(
top: 10,
right: 10,
child: Container(
alignment: Alignment.center,
height: 35,
width: 35,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.black.withOpacity(.65)),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CustomText(
text: '${model.discount}%',
size: 10,
color: Colors.white,
),
CustomText(
text: 'OFF',
size: 10,
color: Colors.white,
),
],
),
),
)
],
),
),
],
),
);
}
}
Here is how i passed the model to the above code from different page
GridView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 1,
childAspectRatio: .69),
itemBuilder: (context, index) {
ItemModel model;
if (dataSnapshot.hasData)
model = ItemModel.fromJson(
dataSnapshot.data.docs[index].data());
//debugPrint(dataSnapshot.data.documents.length.toString());
if (dataSnapshot.hasData)
return CategoryProductCard(
model: model,
);
else
return Text('No more products');
},
itemCount:
dataSnapshot != null ? dataSnapshot.data.docs.length : 0,
);
This is my data collection
import 'package:cloud_firestore/cloud_firestore.dart';
class ItemModel {
String category;
String details;
int discount;
bool isFeatured;
String longDescription;
int mrp;
String pid;
int price;
Timestamp publishedDate;
int quantity;
String shortInfo;
String status;
List thumbnailUrl;
String title;
ItemModel({
this.title,
this.shortInfo,
this.publishedDate,
this.thumbnailUrl,
this.longDescription,
this.status,
});
ItemModel.fromJson(Map<String, dynamic> json) {
category = json['category'];
details = json['details'];
discount = json['discount'];
isFeatured=json['isFeatured'];
longDescription = json['longDescription'];
mrp = json['mrp'];
pid = json['pid'];
price = json['price'];
publishedDate = json['publishedDate'];
quantity = int.parse(json['quantity']);
shortInfo = json['shortInfo'];
status = json['status'];
thumbnailUrl = json['thumbnailUrl'];
title = json['title'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['title'] = this.title;
data['shortInfo'] = this.shortInfo;
data['price'] = this.price;
if (this.publishedDate != null) {
data['publishedDate'] = this.publishedDate;
}
data['thumbnailUrl'] = this.thumbnailUrl;
data['longDescription'] = this.longDescription;
data['status'] = this.status;
data['details'] = this.details;
return data;
}
}
class PublishedDate {
String date;
PublishedDate({this.date});
PublishedDate.fromJson(Map<String, dynamic> json) {
date = json['$date'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['$date'] = this.date;
return data;
}
}
Model giving all the deatils except thumbUrl , Don't know why this is happening , Thanks in advance
That because thumbnailUrl is empty not valued yet.
You have to wait the Future that set the values on thumbnailUrl then setState to refresh the Widget.
However to avoid the error you can do something like that:
children: [
model.thumbnailUrl.length > 0 ?
ClipRRect(
borderRadius: BorderRadius.only(topLeft: Radius.circular(5), topRight: Radius.circular(5)),
child: Image.network(
model.thumbnailUrl[0],
height: 150,
width: size.width * .48,
fit: BoxFit.fill,
),
) : CircularProgressIndicator() ,
//.other widgets here
]
hey why is my itemcount not working i have 6 rows in my database but when i run the code it show me only one row and the other rows not showing it
this is my code:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class my_ads extends StatefulWidget {
const my_ads({Key? key}) : super(key: key);
#override
State<my_ads> createState() => _my_adsState();
}
List list = [];
int select_item = 0;
class _my_adsState extends State<my_ads> {
#override
Future ReadData() async {
var url = "https://***.***.***.**/getData.php";
var res = await http.get(Uri.parse(url));
if (res.statusCode == 200) {
var red = jsonDecode(res.body);
setState(() {
list.addAll(red);
});
print(list);
}
}
#override
void initState() {
super.initState();
GetData();
}
GetData() async {
await ReadData();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: list.length,
itemBuilder: ((cts, i) {
return Container(
height: 800,
child: ListView(
children: [
Container(
margin: EdgeInsets.only(left: 70, right: 60),
height: 54.0,
width: 224.0,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Color(0xffF4AC47), width: 5),
color: Color(0xff42A9D2),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(40),
bottomRight: Radius.circular(40))),
child: new Center(
child: new Text(
"MyAds",
style: TextStyle(
fontSize: 25,
color: Color(0xff072A52),
fontFamily: 'Cairo'),
textAlign: TextAlign.center,
),
//end logo
)),
),
///start Section
Container(
margin: EdgeInsets.only(left: 10, right: 10, top: 10),
height: 180.0,
width: 430.0,
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Color(0xff42A9D2), width: 5),
borderRadius: BorderRadius.circular(8)),
child: new Container(
child: Row(
children: [
Expanded(
child: Image(
image: AssetImage("assets/book.jpg"),
)),
Container(
margin: EdgeInsets.only(
left: 110, top: 30, right: 13),
child: Column(
children: [
Text(
"test",
style: TextStyle(
fontSize: 20, color: Colors.black87),
),
SizedBox(
height: 20,
),
Row(
children: [
Text("test2"),
Icon(Icons.perm_identity_rounded)
],
),
SizedBox(
height: 5,
),
Row(
children: [
Text("}"),
Column(
children: [Icon(Icons.store)],
)
],
),
],
),
)
],
)
//end logo
)),
),
],
),
);
})));
}
}
i tried to change ListView to ListTile but the design will be detroyed becuse i need to make the same design to other pages but my problem is with itemcount its not making any changes ! please if you have any ideas with my problem give me ansewrs
I am building a Job Find app on flutter and I am facing some State Management problems. I have a screen where I show all of my job listings (job_list_screen.dart) and if the user press on a job the app loads this specific job with all the details(job_details_screen.dart).
enter image description here
enter image description here
As you can see, I have an apply button(the blue button) on both screens. When I press apply on the job_details_screen I send a put request on my database and it works fine. But, when I go back to my job_list_screen the button doesn't change even thought I wrapped it with a Consumer.
enter image description here
enter image description here
Here is all the code I wrote with the providers, the **screens **and the **widgets **I use.
The jobs provider:
First of all, this is how I fetch jobs from the API and I insert all my data in a List model:
`
/*
|--------------------------------------------------------------------------
| Fetch Jobs from database
|--------------------------------------------------------------------------
|
| 1. set the url for this function
| 2. GET the response from the server only if you are authenticated
| 3. Decode the
response.body: {
'listings': {
'data': (*Inside here, there are all the job list*)
}
}
| 4. For every job inside the data response
| add a new Job item in the List<Job>
| with the named variables from the current data.reposnse.job
*/
Future<List<Job>?> fetchJobs() async {
final key = await storage.read(key: 'auth');
final baseUrl = AppUrl.baseUrl;
try {
// 1.
var url = Uri.parse('$baseUrl/listings');
// 2.
var response = await http.get(
url,
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer $key',
},
);
// print(key);
if (response.statusCode == 200 || response.statusCode == 201) {
// 3.
var jsonResponse = jsonDecode(response.body)['listings']['data'];
_jobs = [];
// 4.
for (var j in jsonResponse) {
Job job = Job(
id: j['id'],
title: j['title'],
employmentType: j['employmentType'],
major: j['major'],
city: j['city'],
companyName: j['companyName'],
experience: j['experience'],
date: j['date'],
views: j['views'],
description: j['description'],
benefits: j['benefits'],
requirements: j['requirements'],
hasApplied: j['hasApplied'],
hasViewed: j['hasViewed'],
);
_jobs.add(job);
notifyListeners();
}
notifyListeners();
return _jobs;
} else {
throw Exception('Problem loading jobs');
}
} catch (e) {
print(e);
}
}
`
This is the function that I call when the user presses the apply button:
`
/*
|--------------------------------------------------------------------------
| Apply for a job
|--------------------------------------------------------------------------
*/
Future<void> applyJob(String id) async {
final key = await storage.read(key: 'auth');
final baseUrl = AppUrl.baseUrl;
try {
var url = Uri.parse('$baseUrl/listings/$id/apply');
var response = await http.put(
url,
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer $key',
},
);
if (response.statusCode == 200 || response.statusCode == 201) {
print(jsonDecode(response.body));
_hasApplied = jsonDecode(response.body)['hasApplied'];
notifyListeners();
} else {
print(jsonDecode(response.body));
notifyListeners();
}
} catch (e) {
print(e);
}
notifyListeners();
}
`
The job_card widget:
`
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:final_try/screens/job_details_screen.dart';
import '../models/job.dart';
import '../providers/jobs.dart';
import '../styles/colors.dart';
class JobCardBig extends StatefulWidget {
static const routeName = '/job-card-big';
#override
State<JobCardBig> createState() => _JobCardBigState();
}
class _JobCardBigState extends State<JobCardBig> {
#override
Widget build(BuildContext context) {
final job = Provider.of<Job>(context, listen: true);
return Container(
padding: EdgeInsets.all(10),
margin: EdgeInsets.only(bottom: 10),
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(color: lightgrey, width: 1),
borderRadius: BorderRadius.circular(5.0),
boxShadow: [
BoxShadow(
color: lightgrey.withOpacity(.5),
spreadRadius: 1,
blurRadius: 2,
offset: Offset(0, 1), // changes position of shadow
),
],
color: white,
),
child: Column(children: [
Container(
child: Row(
children: [
Container(
height: 50,
width: 50,
alignment: Alignment.center,
decoration:
BoxDecoration(shape: BoxShape.circle, color: lightgrey),
),
SizedBox(
width: 10,
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Container(
height: 70,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(
job.title.toString(),
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Text(
job.companyName.toString(),
style: TextStyle(
fontSize: 14,
color: lightgrey,
),
),
],
),
),
),
Container(
height: 70,
width: 50,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(
Icons.remove_red_eye,
size: 14,
color: darkgrey,
),
SizedBox(
width: 5,
),
Text(
job.views == null
? job.views = '0'
: job.views.toString(),
style: TextStyle(
fontSize: 14,
color: darkgrey,
),
),
],
),
],
),
),
],
),
),
],
)),
SizedBox(
height: 5,
),
Divider(
thickness: 1,
),
SizedBox(
height: 5,
),
Container(
height: 80,
alignment: Alignment.bottomLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'Είδος Απασχόλησης:',
),
SizedBox(
width: 5,
),
Text(
Provider.of<Jobs>(context, listen: false)
.jobTypeFormat(job.employmentType.toString()),
style: TextStyle(color: lightgrey),
),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Προϋπηρεσία:'),
SizedBox(
width: 5,
),
Flexible(
child: job.experience == null
? Text(
'Δεν απαιτείται',
style: TextStyle(color: lightgrey),
)
: job.experience! > 1
? Text(
'${job.experience.toString()} χρόνια',
style: TextStyle(color: lightgrey),
)
: Text(
'${job.experience.toString()} χρόνο',
style: TextStyle(color: lightgrey),
),
),
],
),
Row(
children: [
Text('Τοποθεσία:'),
SizedBox(
width: 5,
),
Text(
job.city.toString(),
style: TextStyle(color: lightgrey),
),
],
),
Row(
children: [
Text('Δημοσιεύθηκε:'),
SizedBox(
width: 5,
),
Text(
Provider.of<Jobs>(context, listen: false)
.dateFormat(job.date),
// job.date.toString(),
style: TextStyle(color: lightgrey),
),
],
),
],
),
),
Container(
margin: EdgeInsets.only(top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
GestureDetector(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
border: Border.all(color: darkgrey, width: 1),
borderRadius: BorderRadius.circular(5.0),
color: darkgrey,
),
child: Text(
'Περισσότερα',
style: TextStyle(color: white),
),
),
onTap: () {
Navigator.of(context)
.pushNamed(JobDetailsScreen.routeName, arguments: job.id)
.then((_) {
// Provider.of<Jobs>(context, listen: false).fetchJobs();
});
},
),
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: job.hasApplied == 1
? Color.fromARGB(255, 196, 76, 68)
: buttonColor,
),
child: Consumer<Job>(
builder: (context, job, child) {
return Text(
job.hasApplied == 1 ? 'Δεν ενδιαφέρομαι' : 'Αίτηση',
style: TextStyle(
color: white,
),
);
},
),
),
],
),
),
]),
);
}
}
`
The job_list_screen:
Here I load all my job_card widgets with ListView.builder
`
import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import '../styles/colors.dart';
import '../providers/jobs.dart';
import '../widgets/header_screen.dart';
import '../widgets/job_card_big.dart';
class JobListScreen extends StatefulWidget {
static const routeName = '/job-list-screen';
const JobListScreen({super.key});
#override
State<JobListScreen> createState() => _JobListScreenState();
}
class _JobListScreenState extends State<JobListScreen> {
final controller = ScrollController();
bool _firstLoading = true;
var _isLoading = false;
int page = 1;
final _formKey = GlobalKey<FormState>();
String? _searchText;
bool _isFiltered = false;
#override
void initState() {
controller.addListener(() {
if (controller.position.maxScrollExtent == controller.offset) {
fetch();
}
});
super.initState();
}
Future fetch() async {
if (!_isFiltered) {
setState(() {
_isLoading = true;
page++;
Provider.of<Jobs>(context, listen: false)
.fetchMore(page)
.then((_) => _isLoading = false);
});
}
}
#override
void didChangeDependencies() {
if (_firstLoading) {
Provider.of<Jobs>(context, listen: true).fetchJobs().then((_) {
setState(() {
_firstLoading = false;
});
});
}
super.didChangeDependencies();
}
void searchJob() {
if(_searchText == null || _searchText == ''){
setState(() {
_isFiltered = false;
});
}
else setState(() {
Provider.of<Jobs>(context, listen: false).filterJobs(_searchText!);
_isFiltered = true;
});
}
#override
Widget build(BuildContext context) {
final jobsData = Provider.of<Jobs>(context, listen: true);
var jobsList = jobsData.jobs;
var filteredList = jobsData.filteredJobs;
// var jobsListFiltered = jobsData.filteredJobs;
return Scaffold(
body: Stack(
children: [
Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.only(
top: 20,
right: 20,
left: 20,
),
child: Column(
children: [
HeaderScreen(title: 'Αγγελίες'),
Container(
child: Form(
key: _formKey,
child: Row(
children: [
Expanded(
child: Container(
child: TextFormField(
decoration: InputDecoration(
hintText: 'Enter some text',
),
onSaved: (value) {
_searchText = value;
},
),
),
),
Container(
margin: EdgeInsets.only(top: 10, bottom: 5),
height: 40,
width: 40,
child: ElevatedButton(
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.all<Color>(white),
backgroundColor: MaterialStateProperty.all<Color>(
primaryColor),
),
child: Container(
child: Icon(Icons.search),
),
onPressed: () {
_formKey.currentState?.save();
searchJob();
},
),
),
],
),
),
),
SizedBox(
height: 10,
),
Divider(
thickness: 1,
),
SizedBox(
height: 10,
),
Expanded(
child: !_isFiltered
? Container(
child: !_firstLoading
? ListView.builder(
controller: controller,
itemCount: jobsList.length,
itemBuilder: (ctx, i) =>
ChangeNotifierProvider.value(
value: jobsList[i],
child: Column(
children: [
JobCardBig(),
],
),
),
)
: Center(
child: CircularProgressIndicator(),
),
)
: Container(
child: !_firstLoading
? ListView.builder(
controller: controller,
itemCount: filteredList.length,
itemBuilder: (ctx, i) =>
ChangeNotifierProvider.value(
value: filteredList[i],
child: Column(
children: [
JobCardBig(),
],
),
),
)
: Center(
child: CircularProgressIndicator(),
),
),
),
],
),
),
Positioned(
child: _isLoading
? Container(
width: double.infinity,
height: MediaQuery.of(context).size.height,
color: Color.fromARGB(52, 0, 0, 0),
child: Center(
child: CircularProgressIndicator(),
),
)
: Container(),
),
],
),
);
}
}
`
I tried to load my fetchJobs() function when the user exits the job_details_screen but even though it works, it is not the right solution. The reason why I say that this is not the right way, is because of this possible scenario:
If the user scrolls down a lot, and the app load 60 jobs, then if he presses on job 60, and he exit the job_details_screen, the app will load the first 15 jobs and the user will have to scroll down again. And that's not the user experience I want to provide.
I am searching for a solution that will update only the apply button and it will not need to recreate the whole list. Plus, with this solution the user will go back to the same scroll point he was when he entered the job_details_screen.
I hope I explained my problem properly. This is the first time I upload a question here and I would also like to mention that this is my first project on flutter so don't judge my code too harshly.
Thanks in advance!!
I have a POST API that when I send a request, I give the GET API request on the same screen to show the json data.
When I send information, after sending the information, the Get data is not displayed and must be logged out to display GET API data.
How can I refresh the page after sending the POST API data, so that the information is displayed after sending
POST API:
void ladderAsli() async {
if (_avgWeeklySales.text.isNotEmpty) {
print(token);
var response = await http.post(
Uri.parse("localhost/backend/api/v1/pellekan/main/add/"),
body: ({
"avgWeeklySales": _avgWeeklySales.text,
}),
headers: {
'Authorization': 'Bearer $token',
});
var body = jsonDecode(response.body);
if (response.statusCode == 200) {
SharedPreferences pref = await SharedPreferences.getInstance();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('${body['success']}')));
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('${body['error']}')));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('error')));
}
}
and GET API:
Future getDataLadder() async {
print('bye');
String token = await getToken();
var response = await http.get(
Uri.parse('localhost/backend/api/v1/pellekan/main/active'),
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
});
print('Token : ${token}');
print('Response Body : ${response.body}');
if (response.statusCode == 400) {
var chieIN = jsonDecode(response.body);
print("be moshkel khordim hich dataei nist");
}
if (response.statusCode == 200) {
var chieIN = jsonDecode(response.body);
// print('Hosssssein ' +
// chieIN['pellekanInfo']['pellekanPublishStatus'].toString());
val = chieIN['pellekanInfo']['pellekanPublishStatus'].toString();
print('BODOBA : ${val}');
setState(() {
val = '0';
});
//setState(() {
// stringResponse = jsonDecode(response.body)['pellekan'];
// val!.add(chieIN['pellekanInfo']['pellekanPublishStatus'].toString());
stringResponse = [];
stringResponse.addAll(List<NardebanData>.from(json
.decode(response.body)['pellekan']
.map((x) => NardebanData.fromJson(x))));
print('String Response : ${stringResponse}');
// nardeban_data = (stringResponse as List<NardebanData>).map((d) => NardebanData.fromJson(d)).toList();
//});
} else {
print("error");
}
}
in the initState call getDataLadder()
Refreshpage
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:project/pattern_formatter.dart';
import 'package:project/screens/result-ladder.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
List<NardebanData> nardeban_data = [];
List<NardebanData> stringResponse = [];
class Ladder extends StatefulWidget {
const Ladder({Key? key}) : super(key: key);
#override
_LadderState createState() => _LadderState();
}
Future<String> getToken() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('login')!;
}
class _LadderState extends State<Ladder> {
bool value = true;
String? val = "";
String token = "";
#override
void initState() {
super.initState();
getDataLadder();
getInfo();
}
void getInfo() async {
SharedPreferences pref = await SharedPreferences.getInstance();
setState(() {
token = pref.getString("login")!;
});
}
TextEditingController _avgWeeklySales = TextEditingController();
TextEditingController _doubleSellingPricePercent = TextEditingController();
TextEditingController _tripleSellingPricePercent = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Directionality(
textDirection: TextDirection.rtl, child: gochgochApp()));
}
Future getDataLadder() async {
print('bye');
String token = await getToken();
var response = await http.get(
Uri.parse('localhost/backend/api/v1/pellekan/main/active'),
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
});
print('Token : ${token}');
print('Response Body : ${response.body}');
if (response.statusCode == 400) {
var chieIN = jsonDecode(response.body);
print("be moshkel khordim hich dataei nist");
}
if (response.statusCode == 200) {
var chieIN = jsonDecode(response.body);
// print('Hosssssein ' +
// chieIN['pellekanInfo']['pellekanPublishStatus'].toString());
val = chieIN['pellekanInfo']['pellekanPublishStatus'].toString();
print('BODOBA : ${val}');
setState(() {
val = '0';
});
//setState(() {
// stringResponse = jsonDecode(response.body)['pellekan'];
// val!.add(chieIN['pellekanInfo']['pellekanPublishStatus'].toString());
stringResponse = [];
stringResponse.addAll(List<NardebanData>.from(json
.decode(response.body)['pellekan']
.map((x) => NardebanData.fromJson(x))));
print('String Response : ${stringResponse}');
// nardeban_data = (stringResponse as List<NardebanData>).map((d) => NardebanData.fromJson(d)).toList();
//});
} else {
print("hooooooooooooooooooooooooo");
}
}
// Future asyncokeyeData() async {
// SharedPreferences pref = await SharedPreferences.getInstance();
// val = pref.getString('okeyeData');
// }
Widget gochgochApp() {
print('Valiable : ${val}');
if (val == '0') {
print(val);
// return Container(
// height: 200.0,
// child: Center(child: Text('شما در انتظار تایید نیست')),
// );
// return alertInForProcessLadder();
return getBody();
// return getBody();
}
// if (val == '2' || val == null) {
// return getForm();
// }
else {
return getForm();
}
}
Widget alertInForProcessLadder() {
return (SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 24),
child: SingleChildScrollView(
child: Container(
child: Center(
child: Text(
'شما یک پلکان اصلی در انتظار تایید ادمین دارید و نمی توانید پلکان دیگری ایجاد کنید')),
height: 200.0,
),
)),
));
}
Widget getForm() {
return (SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 24),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 9,
),
Text(
"فرم نردبان اصلی",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18,
color: Colors.blue,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 10,
),
Container(
padding: EdgeInsets.all(28),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Text(
'مبلغ را به تومان وارد کنید',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 4,
),
TextField(
controller: _avgWeeklySales,
textAlign: TextAlign.center,
cursorColor: Colors.blue,
keyboardType: TextInputType.number,
inputFormatters: [ThousandsFormatter()],
decoration: InputDecoration(
hintStyle:
TextStyle(color: Colors.black26, fontSize: 13),
hintText: 'مثال : 1,000,000',
border: OutlineInputBorder(),
hintTextDirection: TextDirection.rtl,
contentPadding: EdgeInsets.all(8),
),
),
SizedBox(
height: 22,
),
Text(
'درصد تخفیف برای 20 عدد',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 4,
),
TextField(
controller: _doubleSellingPricePercent,
textAlign: TextAlign.center,
cursorColor: Colors.blue,
keyboardType: TextInputType.number,
inputFormatters: [ThousandsFormatter()],
decoration: InputDecoration(
hintStyle:
TextStyle(color: Colors.black26, fontSize: 13),
hintText: 'مثال : 20',
border: OutlineInputBorder(),
hintTextDirection: TextDirection.rtl,
contentPadding: EdgeInsets.all(8),
),
),
SizedBox(
height: 22,
),
Text(
'درصد تخفیف برای 30 عدد',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 13,
color: Colors.black54,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 4,
),
TextField(
controller: _tripleSellingPricePercent,
textAlign: TextAlign.center,
cursorColor: Colors.blue,
keyboardType: TextInputType.number,
inputFormatters: [ThousandsFormatter()],
decoration: InputDecoration(
hintStyle:
TextStyle(color: Colors.black26, fontSize: 13),
hintText: 'مثال : 30',
border: OutlineInputBorder(),
hintTextDirection: TextDirection.rtl,
contentPadding: EdgeInsets.all(8),
),
),
SizedBox(
height: 25,
),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
ladderAsli();
},
style: ButtonStyle(
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
),
foregroundColor:
MaterialStateProperty.all<Color>(Colors.white),
backgroundColor:
MaterialStateProperty.all<Color>(Colors.blue),
),
child: Padding(
child: Text(
'تایید',
style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 21),
),
padding: EdgeInsets.all(15.0),
),
),
),
],
),
),
],
),
)),
));
}
Widget getBody() {
var size = MediaQuery.of(context).size;
return Container(
width: size.width,
height: size.height,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10),
bottomRight: Radius.circular(10)),
color: Colors.white),
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Container(
height: 1,
decoration:
BoxDecoration(color: Colors.grey.withOpacity(0.2)),
),
),
SizedBox(
width: 10,
),
buildHeader(
text: 'جهت فعال سازی پله 30 عددی فیلد زیر را فعال کنید',
child: buildSwitch(),
),
SizedBox(
width: 10,
),
Flexible(
child: Container(
height: 1,
decoration:
BoxDecoration(color: Colors.grey.withOpacity(0.2)),
),
),
],
),
SizedBox(
height: 15,
),
Column(
children: List.generate(stringResponse.length, (index) {
NardebanData dataItem = stringResponse[index];
return Column(
children: [
Padding(
padding: const EdgeInsets.only(right: 5, left: 5),
child: Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/images/bg.png"),
fit: BoxFit.fill,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: 90,
// width: (size.width - 20) * 0.68,
child: Row(
children: [
SizedBox(width: 20), // give it width
Container(
width: 60,
decoration: BoxDecoration(
color: Colors.blue,
border:
Border.all(color: Colors.blue),
borderRadius:
BorderRadius.circular(40.0)),
child: Padding(
padding: EdgeInsets.all(10.0),
child: Text(dataItem.name!,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12.5,
fontWeight: FontWeight.bold,
color: Colors.white)))),
SizedBox(
width: 10,
),
Container(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
dataItem.form ?? '' + '',
style: TextStyle(
fontSize: 14,
color: Colors.black54,
fontWeight: FontWeight.w400),
overflow: TextOverflow.ellipsis,
),
],
),
),
Container(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
' تا ' + dataItem.to!,
style: TextStyle(
fontSize: 14,
color: Colors.black54,
fontWeight: FontWeight.w400),
overflow: TextOverflow.ellipsis,
),
],
),
)
],
),
),
Container(
width: (size.width - 120) * 0.32,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue)),
child: Padding(
padding: const EdgeInsets.only(
right: 10,
bottom: 4,
left: 10,
top: 4),
child: Row(
children: [
SizedBox(
width: 25,
height: 25,
child: TextField(
textAlign: TextAlign.center,
keyboardType:
TextInputType.number,
decoration: InputDecoration(
hintText: dataItem.percent!,
border: InputBorder.none,
contentPadding: EdgeInsets.only(
bottom: 8,
top: 3,
),
),
),
)
],
),
),
),
// Icon(
// Icons.notifications,
// size: 22,
// color: Colors.blue.withOpacity(0.7),
// )
],
),
)
],
),
)),
],
);
})),
],
),
),
);
}
Widget buildHeader({
required Widget child,
required String text,
}) =>
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
text,
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
const SizedBox(height: 3),
child,
],
);
Widget buildSwitch() => Transform.scale(
scale: 2,
child: Switch.adaptive(
activeColor: Colors.blueAccent,
activeTrackColor: Colors.blue.withOpacity(0.4),
// inactiveThumbColor: Colors.orange,
// inactiveTrackColor: Colors.black87,
splashRadius: 50,
value: value,
onChanged: (value) => setState(() => this.value = value),
),
);
void ladderAsli() async {
if (_avgWeeklySales.text.isNotEmpty) {
print(token);
var response = await http.post(
Uri.parse("localhost/backend/api/v1/pellekan/main/add/"),
body: ({
"avgWeeklySales": _avgWeeklySales.text,
"doubleSellingPricePercent": _doubleSellingPricePercent.text,
"tripleSellingPricePercent": _tripleSellingPricePercent.text,
}),
headers: {
'Authorization': 'Bearer $token',
});
var body = jsonDecode(response.body);
if (response.statusCode == 200) {
SharedPreferences pref = await SharedPreferences.getInstance();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('${body['success']}')));
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('${body['error']}')));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text('مبلغ کل را وارد کنید')));
}
}
}
this is json sample:
{
"pellekan": [
{
"name": "پله 1",
"form": null,
"to": "9999",
"percent": 1
},
{
"name": "پله 2",
"form": "9999",
"to": 10.74,
"percent": 2.89
},
{
]
}
Listview.builder widget used to propagate the change in ui
ListView.builder(
itemCount: datajson!.length,
itemBuilder: (context, index) {
return Text(datajson![index].toString(),
style: TextStyle(fontSize: 10));
})
Here i use sample post and getmethod with future delay like mimic the api wait and supply the data.
void MygetData() {
Future.delayed(Duration(seconds: 3), () {
setState(() {
isloading = false;
datajson;
});
});
}
void posts() {
Future.delayed(Duration(seconds: 3), () {
// other post request
datajson?.add({"name": "2"});
MygetData();
});
}
SampleCode dartpad live
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
int myvalue = 0;
List<Map<String, dynamic>>? datajson = [];
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
bool isloading = false;
#override
void initState() {
isloading = true;
Future.delayed(Duration(seconds: 3), () {
setState(() {
datajson?.add({"name": "1"});
isloading = false;
});
});
}
void MygetData() {
Future.delayed(Duration(seconds: 3), () {
setState(() {
isloading = false;
datajson;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
// shrinkWrap: true,
children: [
Container(
height: 45,
child: ElevatedButton(
onPressed: () {
setState(() {
isloading = true;
});
posts();
},
child: Text(
"Post",
style: TextStyle(fontSize: 10),
)),
),
Expanded(
child: ListView.builder(
itemCount: datajson!.length,
itemBuilder: (context, index) {
return Text(datajson![index].toString(),
style: TextStyle(fontSize: 10));
}),
),
isloading
? Container(
height: 50,
width: 50,
child: CircularProgressIndicator(),
)
: Text("")
],
),
);
}
void posts() {
Future.delayed(Duration(seconds: 3), () {
// other post request
datajson?.add({"name": "2"});
MygetData();
});
}
}
i think best and easy way to solve this problem.
Navigator.push(context,MaterialPageRoute(builder: (context) =>yourclass()));
but you should fetch data in initstate like this.
void initState() { fetchYourItems(); super.initState(); };
this my screen where i fetch data from API using FutureBuilder . I would like to save data getting from server on device and reuse it when i need . I wouldn't like each time fetch data from the server when i open the screen .
My screen :
and this my code :
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return SafeArea(
/* minimum: const EdgeInsets.only(
top: 20.0, right: 5.0, left: 5.0, bottom: 10.0),*/
child: Center(
child: Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: Color(0xFFF6F7F8),
body: SingleChildScrollView(
child: Form(
key: _formKey,
child: FutureBuilder(
future: future,
// boxApi.getUser(),
builder: (context, snapshot) {
// ignore: missing_return
print(snapshot.data);
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('no connection');
case ConnectionState.active:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator(),
);
break;
case ConnectionState.done:
if (snapshot.hasError) {
return Text('error');
} else if (snapshot.hasData) {
// String price = snapshot.data['body'].;
// print("${snapshot.data}");
return Column(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
Container(
padding: EdgeInsets.only(top: 16),
width: MediaQuery.of(context).size.width,
height:
MediaQuery.of(context).size.height / 4,
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.white60,
blurRadius: 15.0,
offset: Offset(0.0, 0.75))
],
gradient: LinearGradient(
begin: Alignment(0.5, 0.85),
end: Alignment(0.48, -1.08),
colors: [
const Color(0xFF0B0C3A),
const Color(0xFF010611),
],
stops: [
0.0,
0.5,
],
),
//color: blue,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(32),
bottomLeft: Radius.circular(32))),
child: Column(
children: [
Row(
children: [
SizedBox(
width: 30,
),
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
"${snapshot.data.name}",
style: TextStyle(
color: Colors.white,
fontSize: 25,
fontWeight:
FontWeight.bold),
),
SizedBox(
height: 10,
),
Text(
"${snapshot.data.phone}",
style: TextStyle(
color: Colors.white60,
fontSize: 18,
//fontWeight: FontWeight.w300
),
),
])
],
),
Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
Container(
margin: EdgeInsets.symmetric(
vertical: 10),
width: size.width * 0.4,
child: ElevatedButton(
onPressed: () {
if (_nameController.text ==
"" &&
_emailController.text ==
"" &&
_adressController
.text ==
"") {
setState(() =>
isButtonDisabled =
true);
} else {
editUserProfile();
}
},
// editUserProfile();
child: Text('Enregistrer'),
style:
ElevatedButton.styleFrom(
primary: Colors.transparent,
shape:
RoundedRectangleBorder(
borderRadius:
BorderRadius
.circular(
20),
side: BorderSide(
color: Colors
.white)),
),
)),
SizedBox(
width: 20,
),
],
)
],
),
),
Container(
height: MediaQuery.of(context).size.height /
1.5,
// padding: EdgeInsets.only(
// top: 32,
// ),
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Column(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Container(
width: size.width * 0.94,
child: Column(
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(
left: 10,
right: 10,
bottom: 20,
top: 20),
child: Column(
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Text(
'Votre nom :',
style: TextStyle(
color: Color(
0xFF4053FCF),
fontSize: 16,
fontWeight:
FontWeight
.w600),
),
IconButton(
icon: Icon(
CommunityMaterialIcons
.pencil,
color: Colors
.grey,
),
onPressed: () {
myFocusNode
.requestFocus();
setState(() {
enableup =
true;
});
})
],
),
TextFormField(
controller:
_nameController,
enabled: enableup,
focusNode:
myFocusNode,
enableInteractiveSelection:
false,
keyboardType:
TextInputType
.text,
decoration: InputDecoration(
hintText:
"${snapshot.data.name}",
hintStyle: TextStyle(
color: Colors
.grey,
fontSize:
14.0)),
),
Future<User> getUser() async {
SharedPreferences localStorage = await SharedPreferences.getInstance();
String token = localStorage.getString('access_token');
// print(token);
await checkInternet();
Map<String, String> headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token'
};
var url = Uri.parse(ApiUtil.GET_USER);
var response = await http.get(url, headers: headers);
switch (response.statusCode) {
case 200:
var body = jsonDecode(response.body);
// print(body);
User users = User.fromJson(body);
// inspect(users);
// print(users);
return users;
break;
case 404:
throw ResourceNotFound('user');
break;
case 301:
case 302:
case 303:
throw RedirectionFound();
break;
default:
return null;
break;
}
}
How i can save data locally and reuse it without connect to the server ?
Update :
response from api :
{
"id": 53,
"activeboxe_id": 35,
"username": "hamid hamid",
"name": "Hamid Ansari",
"email": "hamid#gmail.com",
"adress": "Germany",
"phone": "21625147147",
"email_verified_at": null,
"created_at": "2021-04-28T10:52:31.000000Z",
"updated_at": "2021-05-28T09:35:17.000000Z",
"role": "user"
}
You could use a SQLite DB.
Consider the docs.
There you can find an example.
Consider using Hive or Object_Box. The are no SQL dbs, and they are very fast and performant.
If you are using bloc as your state management, HydratedBloc is also available. Which is what I use personally