如何使用提供程序在 Flutter ui 中使用 api 响应获取 ListView 构建器数据
Posted
技术标签:
【中文标题】如何使用提供程序在 Flutter ui 中使用 api 响应获取 ListView 构建器数据【英文标题】:How to get ListView builder data using api response in flutter ui using provider 【发布时间】:2020-12-28 22:29:27 【问题描述】:我试图从提供者那里获取响应并在 ui 页面中获取,但是当我尝试向 ui 添加响应时它显示错误
The getter 'data' was called on null. Receiver: null Tried calling: data
在这一行:
ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: doctorList.data.length,
primary: true,
这是正确的方法还是需要更改模态类或 ui 集成。 我通过医生列表访问数据。数据。->数据数据。
我的响应模式类。
import 'dart:convert';
Doctorlist doctorlistFromJson(String str) => Doctorlist.fromJson(json.decode(str));
String doctorlistToJson(Doctorlist data) => json.encode(data.toJson());
class Doctorlist
Doctorlist(
this.status,
this.message,
this.data,
);
int status;
String message;
List<Datum> data;
factory Doctorlist.fromJson(Map<String, dynamic> json) => Doctorlist(
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;
DateTime appointmentDate;
String favourite;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
mobile: json["mobile"],
userImage: json["user_image"],
no: json["no"],
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: DateTime.parse(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.year.toString().padLeft(4, '0')-$appointmentDate.month.toString().padLeft(2, '0')-$appointmentDate.day.toString().padLeft(2, '0')",
"favourite": favourite,
;
我的 Provider 类:
class DoctorListProvider extends ChangeNotifier
Doctorlist doctorList;
Future<Doctorlist> doctorlist() async
try
final response = await http.post(
(Commons.baseURL + "/list"),
headers:
"Accept": "application/json",
"content-type": "application/json",
,body:"id":5);
if (response.statusCode == 200)
var responseJson = Commons.returnResponse(response);
doctorList = Doctorlist.fromJson(responseJson);
print(doctorList);
return Doctorlist.fromJson(responseJson);
else
return null;
on SocketException
return null;
我的 ui 列表视图构建器页面:
class _DoctorState extends State<Doctor>
Doctorlist doctorList;
bool fav = true;
@override
void initState()
doctorList =
Provider.of<DoctorListProvider>(context, listen: false).doctorList;
super.initState();
@override
Widget build(BuildContext context)
ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: doctorList.data.length,
// itemCount: 2,
// reverse: false,
primary: true,
itemBuilder: (BuildContext context, int index)
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: Flexible(
child:
Container(child:
InkWell(
onTap: ()
Navigator.push(context, MaterialPageRoute(builder: (context) => Doctordetails()));
,
child:
Card(
// color: Color(0xff29ABE2),
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: 100,
),
child: Padding(
padding: EdgeInsets.only(
left: 10,
right: 0,
top: 10),
child: Row(
children: <Widget>[
Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <Widget>[
Row(
mainAxisAlignment:
MainAxisAlignment
.start,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <
Widget>[
Container(
decoration:
new BoxDecoration(
borderRadius:
BorderRadius.all(
const Radius.circular(100.0)),
border: Border.all(
color: Colors
.black),
),
height: 70,
width: 70,
child:
ClipRRect(
borderRadius:
BorderRadius.circular(
200),
child: Image
.asset(
'assets/images/registration/profile_side.png',
fit: BoxFit
.fill,
),
),
),
SizedBox(
width: MediaQuery.of(
context)
.size
.height /
80,
),
Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <
Widget>[
Text(
"no",
style: TextStyle(
fontFamily:
"SansBold",
fontSize:
15,
color:
Colors.black),
),
Text(
"no",
style: TextStyle(
fontFamily:
"SansRegular",
fontSize:
15,
color:
Colors.black),
),
SizedBox(
height: 5,
),
SizedBox(
height: MediaQuery.of(context)
.size
.height /
13,
width: MediaQuery.of(context)
.size
.width /
1.9,
child:
AutoSizeText(
'no ',
style: TextStyle(
fontSize:
20),
maxLines:
3,
),
)
],
),
Container(
child:
IconButton(
onPressed:
()
setState(
()
fav =
!fav;
);
,
icon: fav
? Image.asset(
"assets/images/appointment/favourite_unselected.png")
: Image.asset(
"assets/images/appointment/favourite_select.png"),
))
],
),
SizedBox(
height: 5,
),
Row(
children: <
Widget>[
Container(
child: IconButton(
icon: Image
.asset(
"assets/images/appointment/last_appointment.png"),
onPressed:
null),
),
SizedBox(
width: 10,
),
Text(
"Last appointment date",
style: TextStyle(
fontFamily:
"SansRegular",
fontSize:
15,
color: Colors
.black),
)
],
),
Container(
child: Text(
"06-08-2020"),
),
],
),
SizedBox(
width: MediaQuery.of(
context)
.size
.width /
40,
),
],
))))))))
],
);
,
),
我的 Json 响应如下所示。
"status": 1,
"message": "success",
"data": [
"id": "1",
"mobile": "7",
"user_image": "https://hghjfjd.com",
"emr_number": "er-357",
"hospital": "ff",
"status": "1",
"doctor_name": "sanje",
"doc_role": "dfd",
"email": "doctor@gmail.com",
"gender": "Male",
"address": "test mode",
"city": "england",
"state": "tn",
"pincode": "633211",
"clinic_name": "clinic",
"appointment_date": "2020-09-07",
"favourite": "No"
,
【问题讨论】:
【参考方案1】:我如何处理该错误是我根除或将 "" 赋予 null 值。 这是因为您从 API 响应中获取的数据具有空值。 如果您知道哪个值可能为 null,则可以分配一个空 String 值并解决错误。
这是我如何做到这一点的代码。它不专业,但可以完成您的工作。
【讨论】:
另外,最好使用 Consumer 而不是使用 initState 函数。 请不要使用图像作为代码。它消耗更多资源,无法复制/粘贴。 很抱歉,@laurent 没有做对。你在说哪个图像?我在上面粘贴的图像?【参考方案2】:试试这个:
):编辑initState()
方法为:
@override
void initState()
WidgetsBinding.instance.addPostFrameCallback((_) => _afterLayout(context));
): 现在你可以在_afterLayout(context)
方法中加载项目了:
_afterLayout(BuildContext context) async
var docState = Provider.of<DoctorListProvider>(context);
docState.setDoctorList(await docState.doctorlist());
):更新这个类DoctorListProvider
:
class DoctorListProvider extends ChangeNotifier
Doctorlist _doctorList;
Doctorlist get getDoctorList => _doctorList;
set setDoctorList(Doctorlist input)
_doctorList = input;
notifierListners();
...
): 最后在你的 UI 中使用它:
class _DoctorState extends State<Doctor>
bool fav = true;
@override
void initState()
WidgetsBinding.instance.addPostFrameCallback((_) => _afterLayout(context));
@override
Widget build(BuildContext context)
var docState = Provider.of<DoctorListProvider>(context);
return docState.getDoctorList == null ? Container(child: CircularProgressIndicator()) :
ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: docState.getDoctorList.data.length,
// itemCount: 2,
// reverse: false,
primary: true,
itemBuilder: (BuildContext context, int index)
【讨论】:
是的,我已经检查过@Hakiza 列表中有数据 你在哪里调用这个函数Future<Doctorlist> doctorlist() async
?
在单独的文件医生列表提供者中。更新的代码。并在 ui 类中访问它
var docState = Provider.of@override Widget build(BuildContext context)
函数中定义这些。这个函数返回一个Widget
,return docState.getDoctorList == null ? Container(child: CircularProgressIndicator()) : ...
以上是关于如何使用提供程序在 Flutter ui 中使用 api 响应获取 ListView 构建器数据的主要内容,如果未能解决你的问题,请参考以下文章
Flutter StreamProvider 没有将数据推送到 UI
Flutter - 如何在不阻止UI的情况下计算包含未来的繁重任务?
如何在 Flutter Firestore 提供程序中显示数据