如何使用提供程序在 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&lt;Doctorlist&gt; doctorlist() async 在单独的文件医生列表提供者中。更新的代码。并在 ui 类中访问它 var docState = Provider.of(context); docState.getDoctorList == null ? Container(child: CircularProgressIndicator()) :在哪里定义这些?对不起,我是初学者;(谢谢它会有所帮助。@Hazika 您必须在 @override Widget build(BuildContext context) 函数中定义这些。这个函数返回一个Widgetreturn docState.getDoctorList == null ? Container(child: CircularProgressIndicator()) : ...

以上是关于如何使用提供程序在 Flutter ui 中使用 api 响应获取 ListView 构建器数据的主要内容,如果未能解决你的问题,请参考以下文章

Flutter StreamProvider 没有将数据推送到 UI

Flutter 金融应用程序的 UI

Flutter - 如何在不阻止UI的情况下计算包含未来的繁重任务?

如何在 Flutter Firestore 提供程序中显示数据

使用提供程序在 Flutter 中进行 Firebase 电话身份验证 [关闭]

flutter - bloc - 我如何在我的 Ui 中使用 FutureBuilder 来正确实现 Bloc 架构