在 API 中使用用户输入以按用户加载数据时发现预期

Posted

技术标签:

【中文标题】在 API 中使用用户输入以按用户加载数据时发现预期【英文标题】:Expection found while using user input in an API to load data as per user 【发布时间】:2020-11-07 04:33:21 【问题描述】:

我试图从 ListView Builder 中的 API 接收数据,使用用户输入来显示要显示的票证数量。 这是我试图反映用户输入的地方。 每次我在列表视图构建器之前使用文本字段时,我都会收到错误

    import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

class Ticket 
  Ticket(
    this.tickets,
  );

  List<List<List<int>>> tickets;

  factory Ticket.fromJson(Map<String, dynamic> json) => Ticket(
        tickets: List<List<List<int>>>.from(json["tickets"].map((x) =>
            List<List<int>>.from(
                x.map((x) => List<int>.from(x.map((x) => x)))))),
      );

  Map<String, dynamic> toJson() => 
        "tickets": List<dynamic>.from(tickets.map((x) => List<dynamic>.from(
            x.map((x) => List<dynamic>.from(x.map((x) => x)))))),
      ;


class TicketPage extends StatefulWidget 
  @override
  _TicketPageState createState() => _TicketPageState();


class _TicketPageState extends State<TicketPage> 
  String _nos = '0';
  Ticket ticketList;
  String apiResult;
  Map<String, bool> cellStatus = ;
  final numCon = TextEditingController();

  @override
  void initState() 
    super.initState();
    _getNumbers();
    numCon.addListener(_updateUserInput);
  

  _updateUserInput() 
    _nos = numCon.text;
  

  @override
  void dispose() 
// Clean up the controller when the widget is removed from the widget tree.
// This also removes the listener.
    numCon.dispose();
    super.dispose();
  

  _getNumbers() async 
    var result = await http
        .post(
            'https://tickets-qzd55332wa-de.a.run.app/generateTickets?ticketsRequired=$_nos')
        .then((result) 
      //Waits for the API response and assigns to apiResult variable
      setState(() 
        apiResult = result.body;
      );
    );
  

  // List tick = [
  //   
  //     'tickets': [
  //       [
  //         [11, 5, 7, 10, 28, 9, 7, 74, 59],
  //         [1, 15, 7, 10, 8, 79, 27, 74, 9],
  //         [71, 5, 7, 20, 18, 9, 77, 74, 79],
  //       ],
  //       [
  //         [21, 5, 7, 80, 8, 9, 7, 74, 49],
  //         [31, 15, 7, 10, 18, 79, 7, 74, 19],
  //         [71, 5, 7, 20, 18, 79, 77, 74, 29],
  //       ],
  //     ]
  //   ,
  // ];

  @override
  Widget build(BuildContext context) 
    var h = MediaQuery.of(context).size.height;
    var w = MediaQuery.of(context).size.width;

    if (apiResult == null) 
      return Scaffold(body: Center(child: CircularProgressIndicator()));
     else 
      //Get an instance of Ticket from the API assigned to apiResponse variable
      ticketList = Ticket.fromJson(json.decode(apiResult));
      print('Tickets: $ticketList.tickets');

      return Scaffold(
        body: SafeArea(
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.all(28.0),
                child: Container(
                  child: TextField(
                    controller: numCon,
                    decoration: InputDecoration(
                      hintText: 'nos',
                    ),
                  ),
                ),
              ),
              RaisedButton(onPressed: () 
                setState(() 
                  _getNumbers();
                );
              ),
              Center(
                child: Padding(
                  padding: const EdgeInsets.all(20.0),
                  child: Container(
                    decoration: BoxDecoration(
                        border: Border.all(
                      color: Colors.black,
                    )),
                    child: ListView.builder(
                      itemCount: ticketList.tickets.length,
                      itemBuilder: (BuildContext context, index) 
                        List tripleNumbersList = [];
                        List<Widget> cells = [];
                        List<Widget> rows = [];

                        //Get the lists of lists inside the 'tickets' list
                        tripleNumbersList = ticketList.tickets[index];
                        //Iterates over each list with other 3 lists
                        for (int j = 0; j < tripleNumbersList.length; j++) 
                          //Get one of the 3 lists
                          List<int> list = tripleNumbersList[j];
                          //Iterates over the list of numbers
                          for (int k = 0; k < list.length; k++) 
                            //Adds a Widget to 'cells; list for each number
                            cells.add(Container(
                                height: 40,
                                width: 40,
                                decoration: BoxDecoration(
                                  border: Border.all(
                                    color: Colors.black,
                                  ),
                                  //color: Colors.pink
                                ),
                                child: GestureDetector(
                                  onTap: () 
                                    print('Working');
                                    if (cellStatus['$j$k'] ?? true) 
                                      print('Working');
                                      setState(() 
                                        cellStatus.addAll('$j$k': false);
                                      );
                                    
                                  ,
                                  child: list[k] != 0
                                      ? Text(
                                          ' $list[k]  ',
                                          style: TextStyle(
                                              fontSize: 18.0,
                                              fontWeight: FontWeight.bold),
                                        )
                                      : Text(''),
                                )));
                          
                          //Adds the list of 'cells' in the 'rows' list
                          rows.add(Row(children: cells));
                          cells = [];
                        
                        //Adds a empty row to make space
                        rows.add(Row(children: [
                          Container(
                            height: 10,
                          )
                        ]));

                        return Center(
                          child: Container(
                            height: h / 5,
                            decoration: BoxDecoration(
                              border: Border.all(
                                color: Colors.black,
                              ),
                              //color: Colors.pink
                            ),
                            child: Column(
                              //Adds the list of rows to the column
                              children: rows,
                            ),
                          ),
                        );
                      ,
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      );
    
  

它正在抛出异常

RenderBox was not laid out: RenderCustomPaint#aecb2 relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1694 pos 12: 'hasSize'
The relevant error-causing widget was
    ListView 
RenderBox was not laid out: RenderPadding#d9b88 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1694 pos 12: 'hasSize'
The relevant error-causing widget was
    Scaffold 

我希望我能解释这个问题,并希望看到帮助我解决这个问题。 我一直被这个问题困扰。

【问题讨论】:

请看@JideGuru 我确实经历了所有这些例子,现在我坚持这个....尝试使用文本控制器仍然弹出错误。这就是为什么我正在寻找这个问题的帮助@dev-aentgs 这一篇更好地涵盖了这些步骤:Handle changes to a text field。你能用TextEditingController 发布更新的代码吗? 我已经做出了改变...请看@dev-aentgs 【参考方案1】:

由于ListView 嵌套在Column 中而发生错误。

上面的代码可以修改为将ListView包裹在Expanded中。参考this answer

例子:

  @override
  Widget build(BuildContext context) 
    return _buildList(context);
  

  Widget _buildList(BuildContext context) 
    var h = MediaQuery.of(context).size.height;

    if (apiResult == null) 
      return Scaffold(body: Center(child: CircularProgressIndicator()));
     else 
      //Get an instance of Ticket from the API assigned to apiResponse variable
      ticketList = Ticket.fromJson(json.decode(apiResult));
      print('$ticketList.tickets.length Tickets: $ticketList.tickets');

      return SafeArea(
        child: Scaffold(
          appBar: AppBar(
            title: Text('SO 62967820'),
          ),
          body: Column(
            children: [
              Padding(
                padding: const EdgeInsets.all(28.0),
                child: Container(
                  child: TextField(
                    controller: numCon,
                    decoration: InputDecoration(
                      hintText: 'nos',
                    ),
                  ),
                ),
              ),
              RaisedButton(
                  child: Text('Generate'),
                  onPressed: () 
                    setState(() 
                      _getNumbers();
                    );
                  ),
              Expanded(
                child: ListView.builder(
                  itemCount: ticketList.tickets.length,
                  itemBuilder: (BuildContext context, index) 
                    List tripleNumbersList = [];
                    List<Widget> cells = [];
                    List<Widget> rows = [];

                    //Get the lists of lists inside the 'tickets' list
                    tripleNumbersList = ticketList.tickets[index];
                    //Iterates over each list with other 3 lists
                    for (int j = 0; j < tripleNumbersList.length; j++) 
                      //Get one of the 3 lists
                      List<int> list = tripleNumbersList[j];
                      //Iterates over the list of numbers
                      for (int k = 0; k < list.length; k++) 
                        //Adds a Widget to 'cells; list for each number
                        cells.add(Container(
                            height: 40,
                            width: 40,
                            decoration: BoxDecoration(
                              border: Border.all(
                                color: Colors.black,
                              ),
                              //color: Colors.pink
                            ),
                            child: GestureDetector(
                              onTap: () 
                                print('Working');
                                if (cellStatus['$j$k'] ?? true) 
                                  print('Working');
                                  setState(() 
                                    cellStatus.addAll('$j$k': false);
                                  );
                                
                              ,
                              child: list[k] != 0
                                  ? Text(
                                      ' $list[k]  ',
                                      style: TextStyle(
                                          fontSize: 18.0,
                                          fontWeight: FontWeight.bold),
                                    )
                                  : Text(''),
                            )));
                      
                      //Adds the list of 'cells' in the 'rows' list
                      rows.add(Row(children: cells));
                      cells = [];
                    
                    //Adds a empty row to make space
                    rows.add(Row(children: [
                      Container(
                        height: 10,
                      )
                    ]));

                    return Center(
                      child: Container(
                        height: h / 5,
                        decoration: BoxDecoration(
                          border: Border.all(
                            color: Colors.black,
                          ),
                          //color: Colors.pink
                        ),
                        child: Column(
                          //Adds the list of rows to the column
                          children: rows,
                        ),
                      ),
                    );
                  ,
                ),
              ),
            ],
          ),
        ),
      );
    
  

【讨论】:

但是那个扩展的小部件起了什么作用 不完全确定,但根据我对错误的理解和this answer 的解释,Expanded 小部件负责为父级Column 中的ListView 分配适当的高度。 @PratyaySinha 嘿!如果您能看看我面临的这个问题,将不胜感激***.com/questions/68603763/…

以上是关于在 API 中使用用户输入以按用户加载数据时发现预期的主要内容,如果未能解决你的问题,请参考以下文章

在 vue 中保存预填充的输入

PayPal Adaptive Payment Api 预填充用户数据

UIImageView 动画预加载

Select2 预加载数据

如何使用链接从数据库中预填充表单字段?

如何防止在用户输入反应之前从 API 加载数据?