【发布时间】:2021-08-17 11:12:38
【问题描述】:
我正在尝试检索数据并在列表视图中显示,但它显示错误。
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
相关的导致错误的小部件是:
expanse file:///C:/Users/sindh/AndroidStudioProjects/final_project/lib/Dashboard.dart:261:91
当异常被抛出时,这是堆栈:
#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>
这是json解码代码
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;
}
}
这是 API 代码
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();
}
}
}
这是用户界面
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
);
}
}
}
},
),
],
),
),
],
),
),
),
),
);
}
}
【问题讨论】: