Related
I am trying to select an index from a list of images in flutter. While passing the image list to the Image.network() i get an error:
The following NetworkImageLoadException was thrown resolving an image codec:
HTTP request failed, statusCode: 500, http://10.0.2.2:8000/static/product_images/b0bf3474f9c5a6b6cfcf.jpg,http://10.0.2.2:8000/static/product_images/e307dccf6bbc2700e683.jpg,http://10.0.2.2:8000/static/product_images/6e91cff1ce07d72fc127.jpg
Please how do i seperate the images so that only the index i pick is selected?
Below is the Product Model:
import 'dart:convert';
List<ProductModel> productsFromJson(String str) => List<ProductModel>.from(
json.decode(str).map((x) => ProductModel.fromJson(x)));
String productsToJson(List<ProductModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class ProductModel {
ProductModel({
required this.name,
required this.price,
required this.isActive,
required this.imgsUrl,
required this.id,
required this.description,
required this.ownerId,
});
String name;
double price;
bool isActive;
List<String> imgsUrl;
int id;
String description;
int ownerId;
factory ProductModel.fromJson(Map<String, dynamic> json) => ProductModel(
name: json["name"],
price: json["price"].toDouble(),
isActive: json["is_active"],
imgsUrl: List<String>.from(json["imgs_url"].map((x) => x)),
id: json["id"],
description: json["description"],
ownerId: json["owner_id"],
);
Map<String, dynamic> toJson() => {
"name": name,
"price": price,
"is_active": isActive,
"imgs_url": List<dynamic>.from(imgsUrl.map((x) => x)),
"id": id,
"description": description,
"owner_id": ownerId,
};
}
I am using a futurebuilder with dio to fetch the data from the API:
FutureBuilder<List<ProductModel>>(
future: productModel,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('${snapshot.error}');
} else if (snapshot.hasData) {
debugPrint('${snapshot.data}');
return SizedBox(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: Container(
decoration: const BoxDecoration(
color: styles.AppColors.facebookBlue),
child: Text('$finalName products online'),
),
),
Expanded(
child: StaggeredGridView.countBuilder(
crossAxisCount: 2,
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(children: [
Container(
height: 180,
width: double.infinity,
clipBehavior: Clip.antiAlias,
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(4)),
child:
Image.network(snapshot
.data![index].imgsUrl[0])
]),
const SizedBox(
height: 8,
),
Text(snapshot.data![index].name),
Text(
"\$${snapshot.data![index].price.toString()}",
)
],
),
),
);
},
staggeredTileBuilder: (int index) =>
const StaggeredTile.fit(1),
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
),
],
),
);
} else {
return const Center(child: CircularProgressIndicator());
}
}),
For the API call with DioClient:
Future<List<ProductModel>> fetchVProduct() async {
await SecureStorage.readSecureData("vt")
.then((value) => finalToken = value);
try {
final response = await Dio().get(
'$productsEndpoint/me/items/',
options: Options(
headers: {
'Content-Type':
'application/x-www-form-urlencoded;charset=UTF-8;application/json;multipart/form-data',
'Accept': 'application/json',
"Authorization": "Bearer $finalToken",
},
followRedirects: false,
validateStatus: (status) {
return status! < 500;
}),
);
debugPrint(response.toString());
return (response.data as List)
.map((x) => ProductModel.fromJson(x))
.toList();
} on DioError catch (e) {
debugPrint("Status code: ${e.response?.statusCode.toString()}");
throw Exception("Failed to load currently Logged in Vendor Products");
}
}
For the sample json from my apicall:
{
"name": "sa",
"price": 44,
"is_active": true,
"imgs_url": [
"http://10.0.2.2:8000/static/product_images/f3e6421737643e583a1d.jpg, http://10.0.2.2:8000/static/product_images/b53bf8aeb27d27a739cc.jpg, http://10.0.2.2:8000/static/product_images/75a80e7c04ebaed3e425.jpg"
],
"id": 43,
"description": "hfg",
"owner_id": 1
}
Please what do i do next? Thank you.
In data imgs_url is a single string containing three urls.
"imgs_url": [
"http://10.0.2.2:8000/static/product_images/f3e6421737643e583a1d.jpg, http://10.0.2.2:8000/static/product_images/b53bf8aeb27d27a739cc.jpg, http://10.0.2.2:8000/static/product_images/75a80e7c04ebaed3e425.jpg"
],
Change it to
"imgs_url": [
"http://10.0.2.2:8000/static/product_images/f3e6421737643e583a1d.jpg",
"http://10.0.2.2:8000/static/product_images/b53bf8aeb27d27a739cc.jpg",
"http://10.0.2.2:8000/static/product_images/75a80e7c04ebaed3e425.jpg"
],
I am trying to retrieve the data and displaying in a list view but it is showing an error.
The following NoSuchMethodError was thrown building expanse(dirty, dependencies: [MediaQuery], state: _expanseState#6acc3):
The getter 'data' was called on null.
Receiver: null
Tried calling: data
The relevant error-causing widget was:
expanse file:///C:/Users/sindh/AndroidStudioProjects/final_project/lib/Dashboard.dart:261:91
When the exception was thrown, this was the stack:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
#1 _expanseState.build (package:hrms_project/Expenses/expencedashboard.dart:258:39)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4612:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4495:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4667:11)
I/flutter (16460): 200
E/flutter (16460): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: NoSuchMethodError: The getter 'histories' was called on null.
E/flutter (16460): Receiver: null
E/flutter (16460): Tried calling: histories
E/flutter (16460): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:54:5)
E/flutter (16460): #1 _expanseState.initState.<anonymous closure> (package:hrms_project/Expenses/expencedashboard.dart:24:27)
E/flutter (16460): #2 _rootRunUnary (dart:async/zone.dart:1362:47)
E/flutter (16460): #3 _CustomZone.runUnary (dart:async/zone.dart:1265:19)
E/flutter (16460): #4 _FutureListener.handleValue (dart:async/future_impl.dart:152:18)
E/flutter (16460): #5 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:704:45)
E/flutter (16460): #6 Future._propagateToListeners (dart:async/future_impl.dart:733:32)
E/flutter (16460): #7 Future._completeWithValue (dart:async/future_impl.dart:539:5)
E/flutter (16460): #8 _completeOnAsyncReturn (dart:async-patch/async_patch.dart:254:13)
E/flutter (16460): #9 Services.getExpense (package:hrms_project/Api.dart)
E/flutter (16460): <asynchronous suspension>
This is json decode code
import 'dart:convert';
Expense expenseFromJson(String str) => Expense.fromJson(json.decode(str));
String expenseToJson(Expense data) => json.encode(data.toJson());
class Expense {
Expense({
this.success,
this.statusCode,
this.data,
this.message,
});
bool success;
int statusCode;
Data data;
String message;
factory Expense.fromJson(Map<String, dynamic> json) => Expense(
success: json["success"],
statusCode: json["statusCode"],
data: Data.fromJson(json["data"]),
message: json["message"],
);
Map<String, dynamic> toJson() => {
"success": success,
"statusCode": statusCode,
"data": data.toJson(),
"message": message,
};
}
class Data {
Data({
this.histories,
});
List<History> histories;
factory Data.fromJson(Map<String, dynamic> json) => Data(
histories: List<History>.from(json["histories"].map((x) => History.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"histories": List<dynamic>.from(histories.map((x) => x.toJson())),
};
}
class History {
History({
this.id,
this.employeeId,
this.reference,
this.categoryId,
this.currencyId,
this.amount,
this.date,
this.merchant,
this.description,
this.attachments,
this.companyId,
this.status,
});
int id;
EmployeeId employeeId;
Reference reference;
String categoryId;
String currencyId;
String amount;
Date date;
String merchant;
String description;
String attachments;
CompanyId companyId;
String status;
factory History.fromJson(Map<String, dynamic> json) => History(
id: json["id"],
employeeId: employeeIdValues.map[json["employee_id"]],
reference: referenceValues.map[json["reference"]],
categoryId: json["category_id"],
currencyId: json["currency_id"],
amount: json["amount"],
date: dateValues.map[json["date"]],
merchant: json["merchant"],
description: json["description"],
attachments: json["attachments"],
companyId: companyIdValues.map[json["company_id"]],
status: json["status"],
);
Map<String, dynamic> toJson() => {
"id": id,
"employee_id": employeeIdValues.reverse[employeeId],
"reference": referenceValues.reverse[reference],
"category_id": categoryId,
"currency_id": currencyId,
"amount": amount,
"date": dateValues.reverse[date],
"merchant": merchant,
"description": description,
"attachments": attachments,
"company_id": companyIdValues.reverse[companyId],
"status": status,
};
}
enum CompanyId { ECS_934284 }
final companyIdValues = EnumValues({
"ECS-934284": CompanyId.ECS_934284
});
enum Date { THE_00000000 }
final dateValues = EnumValues({
"0000-00-00": Date.THE_00000000
});
enum EmployeeId { EMPMOB_006 }
final employeeIdValues = EnumValues({
"EMPMOB-006": EmployeeId.EMPMOB_006
});
enum Reference { USER }
final referenceValues = EnumValues({
"user": Reference.USER
});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
This is the API code
class Services {
static const String url = 'basic url';
static Future <Expense> getExpense() async {
final response = await http.get(Uri.parse('basic url'));
print(response.statusCode);
if(200 == response.statusCode){
final Expense = expenseFromJson(response.body);
return Expense;
}else{
return Expense();
}
}
}
This is the UI
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_session/flutter_session.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:hrms_project/Api.dart';
import 'package:image_picker/image_picker.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
class getdata {
String category;
String date;
String merchant;
String reference;
String description;
String currencytype;
String amount;
String tax;
getdata({
#required this.category,
#required this.date,
#required this.merchant,
#required this.reference,
#required this.description,
#required this.currencytype,
#required this.amount,
#required this.tax,
});
}
class editpage extends StatefulWidget {
#override
_editpageState createState() => _editpageState();
}
class _editpageState extends State<editpage> {
String SelectDate="Click and select date";
String ctype = "SGD";
String doller = "1";
String _category;
List Category = [
'Allowance',
'Dental Claim',
'Fuel Expense',
'Home base-Taxi/Car RENTAL',
'Home base -mileage',
'IT and Internet Expense',
'Meals and Entertainment',
'Medical Claim',
'Office Supplies',
'Other Expense',
'Transport Claims',
'Travel-Airline',
'Travel-Overseas Allowance',
'Travel Claim',
];
String currencychoose;
List listcurrency = [
'SGD', 'CNY', 'MYR', 'THB', 'TWD', 'USD', 'VND', 'EUR', 'HKD', 'IDR', 'JPY',
];
String taxchoose;
List listTax = [
'GST 0% (0%)',
'GST 7% (7%)',
'Service Charge 10% (10%) ',
];
String Report;
List report = [
"PO-0049-Dominic's",
"PO-0048-April Japan Trip Project",
"PO-0045-Project A March 2021",
"PO-0044-Local Transport-SG",
"PO-0037-Nov2020 Claims",
];
var claimsController = new TextEditingController();
var currencyController = new TextEditingController();
var taxController = new TextEditingController();
var reporttypeController = new TextEditingController();
var merchantController = new TextEditingController();
var selectdateController = new TextEditingController();
var referenceController = new TextEditingController();
var descriptionController = new TextEditingController();
var amountController = new TextEditingController();
void getItemNavigate(BuildContext context) {
Navigator.pop(context);
print("Merchant Name is : ${merchantController.text}");
print("Select Date : ${selectdateController.text}");
print("Reference Code is : ${referenceController.text}");
print("Description is : ${descriptionController.text}");
print("Claims is: ${claimsController.text}");
print("Select Tax : ${taxController.text}");
print(" Amount : ${currencyController.text} ${amountController.text}");
print("Currency Value: ${currencyController.text}");
print("Report: ${reporttypeController.text}");
}
DateTime date = DateTime.now();
Future DatePicker(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: date,
firstDate: new DateTime(DateTime
.now()
.year - 50),
lastDate: new DateTime(DateTime
.now()
.year + 50),
);
if (picked != null && picked != date) {
setState(() {
date = picked;
print(date.toString());
selectdateController.text=DateFormat.yMMMd().format(date).toString();
SelectDate =DateFormat.yMMMd().format(date).toString();
});
}
}
File _pickedImage;
void _pickImageCamera() async{
final picker= await ImagePicker();
final pickedImage= await picker.getImage(source:ImageSource.camera);
final pickedImageFile =File(pickedImage.path);
setState((){
_pickedImage =pickedImageFile;
});
Navigator.pop(context);
}
void _pickImageGallery() async{
final picker= await ImagePicker();
final pickedImage= await picker.getImage(source:ImageSource.gallery);
final pickedImageFile = File(pickedImage.path);
setState((){
_pickedImage =pickedImageFile;
});
Navigator.pop(context);
}
void _Remove(){
setState((){
_pickedImage= null;
});
Navigator.pop(context);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
toolbarHeight: MediaQuery
.of(context)
.size
.height * 0.1,
backgroundColor: Colors.lightBlue[300],
leading: IconButton(icon: Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
Navigator.pop(context);
},
),
centerTitle: true,
title: Text('Edit Expense', style: TextStyle(
fontSize: 20, color: Colors.black, fontWeight: FontWeight.bold),),
),
body: SingleChildScrollView(
child: Container(
color:Colors.grey[200],
child: Container(
width: MediaQuery
.of(context)
.size
.width,
margin: EdgeInsets.only(top:20.0,left: 10,right: 10),
padding: EdgeInsets.all(8.0),
color:Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Category', style: TextStyle(fontSize: 16.0,
fontWeight: FontWeight.w600,
color: Colors.grey[800],)),
SizedBox(height: 8.0),
Container(
margin: EdgeInsets.only(left: 40.0),
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Container(
padding: EdgeInsets.only(left: 16.0, right: 16.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(5.0),
),
child: DropdownButton(
hint: Text('Select Category'),
icon: Icon(
Icons.arrow_drop_down, color: Colors.blue,),
iconSize: 30,
value: _category,
onChanged: (newValue) {
setState(() {
_category = newValue;
claimsController.text=_category;
});
},
items: Category.map((valueItem) {
return DropdownMenuItem(
value: valueItem,
child: Text(valueItem),
);
}).toList(),
),
),
),
),
],
),
),
SizedBox(height: 10),
Radius: BorderRadius.circular(5.0),
),
child: ListTile(
title: Text("${SelectDate}", style: TextStyle(
fontSize: 17, color: Colors.grey[600]),),
trailing: Icon(Icons.arrow_drop_down,color: Colors.blueAccent,size:30),
onTap: () {
DatePicker(context);
},
),
),
),
],
),
),
Container(
width: 180,
height: 50,
child: TextField(
controller: amountController,
textAlign: TextAlign.end,
decoration: InputDecoration(
hintText: "Enter Amount",
border: OutlineInputBorder(
),
),
keyboardType: TextInputType.number,
),
),
],
),
),
],
),
),
child: Row(
children: [
Container(
width: 70,
height: 48,
color: Colors.grey[100],
child: Center(
child: Text('1 ${ctype} =',style:TextStyle(fontSize:16.0,color:Colors.black,)),
),
),
Container(
width: 140,
height: 48,
color: Colors.grey[300],
child: Center(
child: Text('${doller}',style:TextStyle(fontSize:16.0,color:Colors.black,)),
),
),
Container(
width: 47,
height: 48,
color: Colors.grey[100],
child: Center(
child: Text('SGD'),
),
),
],
),
),
],
),
),
SizedBox(height: 10.0),
Container(
margin: EdgeInsets.only(left: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Tax', style: TextStyle(fontSize: 16.0,
fontWeight: FontWeight.w600,
color: Colors.grey[800],)),
SizedBox(height: 6.0),
Container(
margin: EdgeInsets.only(left: 40.0),
child: Padding(
padding: const EdgeInsets.all(1.0),
child: Container(
padding: EdgeInsets.only(left: 16.0, right: 16.0),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(5.0),
),
child: DropdownButton(
hint: Text('Please select the Tax'),
icon: Icon(
Icons.arrow_drop_down, color: Colors.blue,),
iconSize: 30,
value: taxchoose,
onChanged: (newValue) {
setState(() {
taxchoose = newValue;
taxController.text=taxchoose;
});
},
items: listTax.map((valueItem) {
return DropdownMenuItem(
value: valueItem,
child: Text(valueItem),
);
}).toList(),
),
),
),
),
],
),
)
Container(
margin:EdgeInsets.only(left: 30),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Click and select files-->',style: TextStyle(fontSize: 16.0,color:Colors.red),),
RawMaterialButton(
elevation: 6.0,
child: Icon(
Icons.add_a_photo, size: 40, color: Colors.blue,),
padding: EdgeInsets.all(8.0),
shape: CircleBorder(),
onPressed: () {
showDialog(context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Choose option', style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.pinkAccent,),
textAlign: TextAlign.center,
),
content: SingleChildScrollView(
child: ListBody(
children: [
InkWell(
onTap:_pickImageCamera,
splashColor: Colors.purpleAccent,
child: Row(
crossAxisAlignment: CrossAxisAlignment
.center,
),
),
SizedBox(height: 5,),
InkWell(
onTap:_pickImageGallery,
splashColor: Colors.purpleAccent,
child: Row(
crossAxisAlignment: CrossAxisAlignment
.center,
children: [
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.image,
color: Colors
.purpleAccent,
size: 25)
),
Text('Gallery', style: TextStyle(
fontSize: 18,
color: Colors.black,)),
],
),
),
SizedBox(
height: 5
),
InkWell(
onTap:_Remove,
splashColor: Colors.purpleAccent,
child: Row(
crossAxisAlignment: CrossAxisAlignment
.center,
children: [
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.remove_circle,
color: Colors.purpleAccent,
size: 25),
),
],
),
)
],
),
),
);
});
},
),
],
),
),
SizedBox(height:10.0),
Divider(height: 0.1,thickness: 1,color: Colors.grey[200],),
SizedBox(height:5.0),
FlatButton(
color: Colors.lightGreen,
shape:
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child:Text('Save',style: TextStyle(fontSize: 18.0,color:Colors.white),),
onPressed: () async {
var claims = claimsController.text;
var tax = taxController.text;
var reporttype = reporttypeController.text;
var merchant = merchantController.text;
var selectdate = selectdateController.text;
var description = descriptionController.text;
var amount = amountController.text;
var rsp = await claim(claims, amount, selectdate, merchant, tax, description, reporttype);
print(rsp);
if (rsp.containsKey('success') == true) {
print(rsp);
if (rsp['success'] == true) {
Fluttertoast.showToast(
msg: "saved",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.white,
textColor: Colors.green,
fontSize: 16.0
);
}
}
}
},
),
],
),
),
],
),
),
),
),
);
}
}
var result = jsonDecode(response.body);
return Expense.fromJson(result);
try changing it.
My Json response status code is 200 and the object is also created but when I try to bind it with UI in ListView it doesn't show anything. I have used quicktype.io to parse my json data that I received from the API call.
Here's my API_manager.dart file:
import 'package:http/http.dart' as http;
import 'package:aritic/models/contactsModel.dart';
// ignore: camel_case_types
class API_Manager {
Future<ContactsModel> getContacts() async {
var client = http.Client();
var contactsModel;
String contacts_url =
'https://exampleapi.com';
String basicAuth = 'Basic auth key example';
try {
var response = await client.get(contacts_url,
headers: <String, String>{'authorization': basicAuth});
print(response.statusCode);
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
contactsModel = contactsModel.fromJson(jsonMap);
}
} catch (Exception) {
return contactsModel;
}
return contactsModel;
}
}
My UI code:
import 'package:aritic/models/contactsModel.dart';
import 'package:aritic/services/api_manager.dart';
class ContactsPage extends StatefulWidget {
#override
_ContactsPageState createState() => _ContactsPageState();
}
class _ContactsPageState extends State<ContactsPage>
with SingleTickerProviderStateMixin {
Future<ContactsModel> _contactsModel;
bool isSearching = false;
TabController _tabController;
#override
void initState() {
// TODO: implement initState
super.initState();
_tabController = TabController(length: 2, initialIndex: 0, vsync: this);
_tabController.addListener(_handleTabIndex);
}
#override
void dispose() {
_tabController.removeListener(_handleTabIndex);
_tabController.dispose();
super.dispose();
}
void _handleTabIndex() {
setState(() {});
}
#override
Widget build(BuildContext context) {
_contactsModel = API_Manager().getContacts();
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text('Contacts'),
bottom: PreferredSize(
child: Align(
alignment: Alignment.centerLeft,
child: TabBar(
controller: _tabController,
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('Contacts'),
),
Tab(
child: Text('Companies'),
)
],
),
),
preferredSize: Size.fromHeight(40.0)),
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 16.0),
child: IconButton(
icon: Icon(Icons.search),
color: Colors.white,
onPressed: () {},
),
),
],
),
body: TabBarView(controller: _tabController, children: <Widget>[
Container(
height: double.infinity,
child: FutureBuilder<ContactsModel>(
future: _contactsModel,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
padding: const EdgeInsets.all(6),
itemCount: snapshot.data.contacts.length,
itemBuilder: (context, index) {
var contact = snapshot.data.contacts[index];
return Container(
height: 100,
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(contact.owner.username,
style: TextStyle(fontSize: 16))
],
),
);
});
} else
return Center(child: CircularProgressIndicator());
})),
Container(
height: double.infinity,
child: ListView(
padding: const EdgeInsets.all(6),
children: <Widget>[
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Example company',
style: TextStyle(fontSize: 16),
),
Text(
'Example company',
style: TextStyle(fontSize: 14),
)
],
),
),
),
SizedBox(
height: 5,
),
InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (_) => ViewCompany()));
},
child: Container(
height: 50,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'example',
style: TextStyle(fontSize: 16),
),
Text(
'example',
style: TextStyle(fontSize: 14),
)
],
),
),
),
],
)),
]),
floatingActionButton: _bottomButtons(),
));
}
Widget _bottomButtons() {
return _tabController.index == 0
? FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddContacts();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.person_add,
color: Colors.white,
))
: FloatingActionButton(
shape: StadiumBorder(),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return AddCompany();
}));
},
backgroundColor: Colors.cyan,
child: Icon(
Icons.add,
color: Colors.white,
),
);
}
}
Created model(contactsModel.dart):
import 'dart:convert';
ContactsModel contactsModelFromJson(String str) => ContactsModel.fromJson(json.decode(str));
String contactsModelToJson(ContactsModel data) => json.encode(data.toJson());
class ContactsModel {
ContactsModel({
this.total,
this.contacts,
});
String total;
Map<String, Contact> contacts;
factory ContactsModel.fromJson(Map<String, dynamic> json) => ContactsModel(
total: json["total"],
contacts: Map.from(json["contacts"]).map((k, v) => MapEntry<String, Contact>(k, Contact.fromJson(v))),
);
Map<String, dynamic> toJson() => {
"total": total,
"contacts": Map.from(contacts).map((k, v) => MapEntry<String, dynamic>(k, v.toJson())),
};
}
class Contact {
Contact({
this.isPublished,
this.dateAdded,
this.dateModified,
this.createdBy,
this.createdByUser,
this.modifiedBy,
this.modifiedByUser,
this.id,
this.points,
this.color,
this.fields,
this.lastActive,
this.owner,
this.ipAddresses,
this.tags,
this.utmtags,
this.stage,
this.dateIdentified,
this.preferredProfileImage,
this.doNotContact,
this.frequencyRules,
});
bool isPublished;
DateTime dateAdded;
DateTime dateModified;
int createdBy;
String createdByUser;
int modifiedBy;
String modifiedByUser;
int id;
int points;
dynamic color;
Fields fields;
dynamic lastActive;
Owner owner;
List<dynamic> ipAddresses;
List<Tag> tags;
List<dynamic> utmtags;
Stage stage;
DateTime dateIdentified;
dynamic preferredProfileImage;
List<dynamic> doNotContact;
List<dynamic> frequencyRules;
factory Contact.fromJson(Map<String, dynamic> json) => Contact(
isPublished: json["isPublished"],
dateAdded: DateTime.parse(json["dateAdded"]),
dateModified: json["dateModified"] == null ? null : DateTime.parse(json["dateModified"]),
createdBy: json["createdBy"],
createdByUser: json["createdByUser"],
modifiedBy: json["modifiedBy"] == null ? null : json["modifiedBy"],
modifiedByUser: json["modifiedByUser"] == null ? null : json["modifiedByUser"],
id: json["id"],
points: json["points"],
color: json["color"],
fields: Fields.fromJson(json["fields"]),
lastActive: json["lastActive"],
owner: Owner.fromJson(json["owner"]),
ipAddresses: List<dynamic>.from(json["ipAddresses"].map((x) => x)),
tags: List<Tag>.from(json["tags"].map((x) => Tag.fromJson(x))),
utmtags: List<dynamic>.from(json["utmtags"].map((x) => x)),
stage: Stage.fromJson(json["stage"]),
dateIdentified: DateTime.parse(json["dateIdentified"]),
preferredProfileImage: json["preferredProfileImage"],
doNotContact: List<dynamic>.from(json["doNotContact"].map((x) => x)),
frequencyRules: List<dynamic>.from(json["frequencyRules"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"isPublished": isPublished,
"dateAdded": dateAdded.toIso8601String(),
"dateModified": dateModified == null ? null : dateModified.toIso8601String(),
"createdBy": createdBy,
"createdByUser": createdByUser,
"modifiedBy": modifiedBy == null ? null : modifiedBy,
"modifiedByUser": modifiedByUser == null ? null : modifiedByUser,
"id": id,
"points": points,
"color": color,
"fields": fields.toJson(),
"lastActive": lastActive,
"owner": owner.toJson(),
"ipAddresses": List<dynamic>.from(ipAddresses.map((x) => x)),
"tags": List<dynamic>.from(tags.map((x) => x.toJson())),
"utmtags": List<dynamic>.from(utmtags.map((x) => x)),
"stage": stage.toJson(),
"dateIdentified": dateIdentified.toIso8601String(),
"preferredProfileImage": preferredProfileImage,
"doNotContact": List<dynamic>.from(doNotContact.map((x) => x)),
"frequencyRules": List<dynamic>.from(frequencyRules.map((x) => x)),
};
}
class ......{}
Output Screen: here
Json Viewer: here
Dart Devtools: here
This is probably not a problem with your json parsing, but a UI issue. Putting Columns or Rows inside ListViews or the opposite. If there was something wrong with the json, you'd be seeing the return Center(child: CircularProgressIndicator());,
But instead, you're getting an empty UI.
Check your debug console, if you have RenderView errors, or failed to layout render-box issues, this will be the cause of them.
Try using the property of shrink wrap in your lists:
ListView(shrinkwrap:true...
and
ListView.builder(shirinkrap:true...
Also, wrap your Row that inside the ListView with a LimitedBox
i.e
LimitedBox(
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
I have worked a little on a flutter json tutorial, where I am able to fetch and parse json data, I am now trying to put the code into a SliverList. But when I debug my app it throws the follwing error on Builder on line 96: The getter 'length' was called on null. Receiver: null Tried calling: length
I am not sure what to do or what to change. Please note that my app consists of 1 Page with tabbar view.
Here is my full code:
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:innbo_app/product_model.dart';
Future<List> fetchData(http.Client client) async {
final response = await client
.get('http://my-json-server.typicode.com/tariksalihovic/innbo/receipt');
// Use the compute function to run parsePhotos in a separate isolate.
return compute(parseData, response.body);
}
// A function that converts a response body into a List<Photo>.
List parseData(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed.map((json) => Receipt.fromJson(json)).toList();
}
class PlaceholderWidget1 extends StatelessWidget {
final Color color;
PlaceholderWidget1(this.color);
#override
Widget build(BuildContext context) {
return Container(
color: color,
);
}
}
class Indbo1 extends StatelessWidget {
final List data;
Indbo1({Key key, this.data}) : super(key: key);
final List<String> listItems = [];
final List<String> _tabs = <String>[
"Alle",
"Anmeldt",
];
#override
Widget build(BuildContext context) {
return Material(
child: Scaffold(
body: Container(
color: Colors.grey[100],
child: DefaultTabController(
length: _tabs.length, // This is the number of tabs.
child: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
// These are the slivers that show up in the "outer" scroll view.
return <Widget>[
SliverOverlapAbsorber(
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(
context),
sliver: SliverSafeArea(
top: false,
sliver: SliverAppBar(
centerTitle: true,
title: const Text(
"Indbo",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 16,
),
),
floating: true,
pinned: true,
snap: true,
stretch: false,
bottom: TabBar(
// These are the widgets to put in each tab in the tab bar.
tabs: _tabs
.map((String name) => Tab(text: name))
.toList(),
),
),
),
),
];
},
body: TabBarView(
// These are the contents of the tab views, below the tabs.
children: _tabs.map((String name) {
return SafeArea(
top: false,
bottom: false,
child: Builder(
builder: (BuildContext context) {
return CustomScrollView(
key: PageStorageKey<String>(name),
slivers: <Widget>[
SliverOverlapInjector(
// This is the flip side of the SliverOverlapAbsorber above.
handle: NestedScrollView
.sliverOverlapAbsorberHandleFor(context),
),
SliverPadding(
padding: EdgeInsets.fromLTRB(15, 0, 15, 10),
sliver: SliverList(
delegate: SliverChildListDelegate([
SizedBox(height: 30),
Text(
'Genstande',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700),
),
]),
),
),
SliverList(
delegate: SliverChildListDelegate(
[
Container(
child: FutureBuilder<List>(
future: fetchData(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError)
print(snapshot.error);
return snapshot.hasData
? Indbo1(data: snapshot.data)
: Center(
child:
CircularProgressIndicator());
},
),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1.0,
color: Colors.grey[200]),
),
color: Colors.white,
),
margin:
EdgeInsets.only(left: 15, right: 15),
),
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
width: 1.0,
color: Colors.grey[200]),
),
color: Colors.white,
),
margin:
EdgeInsets.only(left: 15, right: 15),
child: ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return ListTile(
/*onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Detail(choice: choices[index])),
);
},*/
leading: CircleAvatar(
radius: 26,
backgroundColor: Colors.grey[400],
child: Icon(Icons.phone_iphone,
color: Colors.white),
),
title: Text(
'${data[index].receiptlines[index].name ?? "Empty"}',
style: TextStyle(
color: Colors.black,
fontSize: 16.5,
fontWeight: FontWeight.w700),
),
subtitle: Text(
'${data[index].orderNumber ?? "Empty"}',
style: TextStyle(
color: Colors.grey[700],
fontSize: 12.0),
),
trailing: Text(
'${data[index].price.amount ?? "Empty"}',
style: TextStyle(
color: Colors.black,
fontSize: 16.5,
fontWeight: FontWeight.w800),
),
);
},
),
),
],
),
),
],
);
},
),
);
}).toList(),
),
),
),
),
),
);
}
}
Here is the product_model.dart which is linked to above code:
class Lines {
final String name;
final String productNumber;
Lines({this.name, this.productNumber});
factory Lines.fromJson(Map<String, dynamic> json) {
return Lines(name: json['name'], productNumber: json['productNumber']);
}
}
class Prices {
final int amount;
Prices({this.amount});
factory Prices.fromJson(Map<String, dynamic> json) {
return Prices(
amount: json['amount'],
);
}
}
class Receipt {
final int id;
final String type;
final String receiptId;
final String orderNumber;
final Prices price;
final List<Lines> receiptlines;
Receipt(
{this.id,
this.type,
this.receiptId,
this.orderNumber,
this.price,
this.receiptlines});
factory Receipt.fromJson(Map<String, dynamic> json) {
var list = json['receiptLines'] as List;
List<Lines> receiptLines =
List<Lines>.from(list.map((i) => Lines.fromJson(i))).toList();
return Receipt(
id: json['id'],
type: json['type'],
receiptId: json['receiptId'],
orderNumber: json['orderNumber'],
price: Prices.fromJson(json['price']),
receiptlines: receiptLines
);
}
}
Im Trying to get data from post http method in flutter, but data has not been processed to ui,
I dont know where i am mistaking. Can any one please answer this?
In ui I got no data on screen. model was generated by online tool, snapshot has no data.
this is my http calling class.
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:my_app/src/model/doctor_res.dart';
import 'package:my_app/src/utils/commons.dart';
// import 'package:my_app/src/widget/doctorcard.dart';
class API_Manager {
Future<DoctorModel> doctorlist() async {
var doctorModel;
var client = http.Client();
try {
var response =
await client.post((Commons.baseURL + "/doc"), headers: {
"content-type": "application/json",
}, body:
{
"id": 5
}
);
print("response");
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
// final doctorModel = doctorModelFromJson(jsonString);
doctorModel = DoctorModel.fromJson(jsonMap);
}
} catch (Exception) {
return doctorModel;
}
return doctorModel;
}
}
this is my Model class
import 'dart:convert';
DoctorModel doctorModelFromJson(String str) => DoctorModel.fromJson(json.decode(str));
String doctorModelToJson(DoctorModel data) => json.encode(data.toJson());
class DoctorModel {
DoctorModel({
this.status,
this.message,
this.data,
});
int status;
String message;
List<Datum> data;
factory DoctorModel.fromJson(Map<String, dynamic> json) => DoctorModel(
status: json["status"],
message: json["message"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"message": message,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.id,
this.mobile,
this.userImage,
this.emrNumber,
this.hospital,
this.status,
this.doctorName,
this.docRole,
this.email,
this.gender,
this.address,
this.city,
this.state,
this.pincode,
this.clinicName,
this.appointmentDate,
this.favourite,
});
String id;
String mobile;
String userImage;
String emrNumber;
String hospital;
String status;
String doctorName;
String docRole;
String email;
String gender;
String address;
String city;
String state;
String pincode;
String clinicName;
String appointmentDate;
String favourite;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
mobile: json["mobile"],
userImage: json["user_image"],
emrNumber: json["emr_number"],
hospital: json["hospital"],
status: json["status"],
doctorName: json["doctor_name"],
docRole: json["doc_role"],
email: json["email"],
gender: json["gender"],
address: json["address"],
city: json["city"],
state: json["state"],
pincode: json["pincode"],
clinicName: json["clinic_name"],
appointmentDate: json["appointment_date"],
favourite: json["favourite"],
);
Map<String, dynamic> toJson() => {
"id": id,
"mobile": mobile,
"user_image": userImage,
"emr_number": emrNumber,
"hospital": hospital,
"status": status,
"doctor_name": doctorName,
"doc_role": docRole,
"email": email,
"gender": gender,
"address": address,
"city": city,
"state": state,
"pincode": pincode,
"clinic_name": clinicName,
"appointment_date": appointmentDate,
"favourite": favourite,
};
}
this is my ui part
class Doctor extends StatefulWidget {
#override
_DoctorState createState() => _DoctorState();
}
class _DoctorState extends State<Doctor> {
Future<DoctorModel> _doctorModal;
// Doctorlist doctorList;
bool fav = true;
#override
void initState() {
_doctorModal = API_Manager().doctorlist();
super.initState();
}
#override
Widget build(BuildContext context) {
return SafeArea(child:
Scaffold(
backgroundColor: Color(0xff29ABE2),
appBar: AppBar(
backgroundColor: Color(0xff29ABE2),
elevation: 0,
// leading: Container(),
title: Row(
children: <Widget>[
Container(
padding:
EdgeInsets.only(left: 0, right: 20, top: 20, bottom: 20),
height: MediaQuery.of(context).size.height * 0.1,
child: ClipRRect(
child: Image.asset(
"assets/images/home/patient.png",
fit: BoxFit.fill,
),
),
),
Container(
padding: EdgeInsets.only(left: 0, right: 100),
child: Text(
"Doc",
style: TextStyle(
fontWeight: FontWeight.w900,
fontFamily: "SansBold",
fontSize: 20),
)),
Container(
padding:
EdgeInsets.only(left: 40, right: 0, top: 25, bottom: 25),
height: MediaQuery.of(context).size.height * 0.1,
// padding: EdgeInsets.all(25),
child: ClipRRect(
child: Image.asset(
"assets/images/home/notification.png",
fit: BoxFit.cover,
),
),
),
],
),
),
drawer: NavigationDrawer(),
body:
// SingleChildScrollView(child:
Container(
// height: MediaQuery.of(context).size.height,
// width: MediaQuery.of(context).size.width,
child:ListView(children: [
Container(
height: MediaQuery.of(context).size.height * 0.90,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40),
topRight: Radius.circular(40),
),
),
child: Padding(
padding: EdgeInsets.all(15),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
children: <Widget>[
Text(
"Your doctors",
style: TextStyle(
fontSize: 18,
fontFamily: "SansBold",
fontWeight: FontWeight.w100),
),
SizedBox(
height: 5,
),
Text(
"Search doctor",
style: TextStyle(
fontSize: 18,
fontFamily: "SansRegular",
fontWeight: FontWeight.w100),
)
],
),
Container(
child: FlatButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>Adddoctor()));
},
// padding: EdgeInsets.only(left: 30, right: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Row(
children: <Widget>[
ImageIcon(
AssetImage("assets/images/home/add_doctor.png"),
color: Colors.white,
),
SizedBox(
width: 5,
),
Text(
"Add doctor",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontFamily: "SansRegular",
fontSize: 20),
),
],
),
color: Color(0xff29ABE2),
)),
],
),
SizedBox(
height: 10,
),
Container(
width: double.infinity,
child: TextField(
style: TextStyle(
color: Colors.black,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.black)),
contentPadding: EdgeInsets.only(top: 14.0),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xff29ABE2))),
hintText: 'Search doctors by ID, Mobile number',
suffixIcon: IconButton(
icon: Icon(Icons.search), onPressed: () {})),
),
),
SizedBox(
height: 8,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
child: FlatButton(
onPressed: () {
},
// padding: EdgeInsets.only(left: 30, right: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
child: Text(
"Search",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontFamily: "SansRegular",
fontSize: 20),
),
color: Color(0xff29ABE2),
)),
],
),
Container(
child:FutureBuilder<DoctorModel>(
future: _doctorModal,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) {
return Text('no data');
} else {
return Text('data present');
}
}
else {
return CircularProgressIndicator(); // loading
}
}
)
The reason why no data was returned from your API_Manager is because the parsed response data was never returned. Adding return when the response was parsed should solve the issue.
if (response.statusCode == 200) {
var jsonString = response.body;
var jsonMap = json.decode(jsonString);
// final doctorModel = doctorModelFromJson(jsonString);
doctorModel = DoctorModel.fromJson(jsonMap);
return doctorModel; // return DoctorModel object
}