【问题标题】:Flutter - How to fix dynamic widgets that are not loading on page load?Flutter - 如何修复在页面加载时未加载的动态小部件?
【发布时间】:2019-10-18 00:53:28
【问题描述】:

我正在创建一个颤振应用程序并创建了一个页面,该页面从 sqlite 数据库中提取数据并动态加载一个小部件,该小部件在页面加载时显示来自 sqlite db 的数据。由于某种原因,小部件未加载。当我热重新加载应用程序时,它仅在调试模式下加载动态小部件。

这是我的代码:

Users userList = new Users();
List details = new List<Widget>();
var db = new DB_Helper();

_addToUserList(Map<dynamic, dynamic> json)
{
    userList.membersList.add(json);
    return userList.membersList;
}

  List<Widget> getTeamMembers()
   { 
    // Get data from db
   db.getMembers().then((data) {
      // clear list to prevent repeating if page refreshes
      userList.membersList.clear();
      details.clear();
      for (Members m  in data)
      {
        Map<String, dynamic> json;
        json = 
        {
          "member_id": m.memberId,
          "member_name": m.memberName,
          "member_email": m.memberEmail
        };
        _addToUserList(json);
      }

       for (Map<dynamic, dynamic> u in userList.membersList) {
        Map<String, dynamic> js = u;
        var emailCtrl = new TextEditingController();
        var name = js["member_name"];
        emailCtrl.text = js["member_email"];

      details.add(

         new Card(
           color: Colors.blue,
        margin: EdgeInsets.all(2),
          child: ExpansionTile(
            title: Text(name),
            children: <Widget>[
               Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.start,
                children: <Widget>[
                    Expanded(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: <Widget>[

                       Container(
                         width: 280,
                         padding: EdgeInsets.all(0),
                         margin: EdgeInsets.all(0),
                         child: TextField(
                           enabled: false,
                           controller: emailCtrl,
                           style: TextStyle(color: Colors.purple),
                           decoration: InputDecoration(
                             labelText: "EMAIL:",
                             labelStyle: new TextStyle(color: Colors.black),
                             border: InputBorder.none,
                           ),
                         ),
                       ),

                      ],
                    ),
                      ),
                ],
              ),
            ],
          ),
        ),                          
      );    
       }

    });

    return details;  
  }

我已尝试获取数据并将其存储在 initState() 中的列表中,但页面仍然加载为空白。

我在查询 sqlite 时尝试使用 await,但它在我调用小部件的脚手架主体属性内引发错误。

它唯一正确加载的时间是,当我删除查询数据库的代码并使用值硬编码 userList 而不是从 sqlite 中将其拉出时。查询 sqlite db 似乎阻止了小部件的显示。如何从 sqlite 中提取数据并将其添加到动态小部件以在页面加载时显示?

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    你的代码肯定有点乱。

    您应该改用ListView.builder。你不应该使用任何 Dart for 循环来构建你的小部件。只需正确设置您的数据数组并使用 ListView.builder 构建卡片和其他小部件。下面是一个使用ListView.builder的例子:

    ListView.builder(
              itemCount: list.length,
              itemBuilder: (BuildContext context, int i) {
                return Dismissible(
                  key: ObjectKey(list[i]),
                  background: Container(
                    alignment: AlignmentDirectional.centerEnd,
                    color: Colors.red,
                    child: Padding(
                      padding: EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 0.0),
                      child: Icon(
                        Icons.delete,
                        color: Colors.white,
                      ),
                    ),
                  ),
                  confirmDismiss: (direction) async {
                    if (direction == DismissDirection.startToEnd) {
                      /// edit item
                      return false;
                    } else if (direction == DismissDirection.endToStart) {
                      /// delete
                      return true;
                    }
                  },
                  onDismissed: (direction) {
                    setState(() {
                      var paymentMethod = list[i];
                      list.removeAt(i);
                      _showDeletePaymentDialog(paymentMethod);
                    });
                  },
                  child: Card(
                    color: BmsColors.primaryBackgroundColor,
                    elevation: 2.0,
                    child: ListTile(
                      title: Text(
                        'xxxx-${list[i].last4}',
                        style: UIUtil.getTxtStyleCaption(),
                      ),
                      subtitle: Text(
                        list[i].brandDisplay,
                        style: UIUtil.getTxtStyleCaption(),
                      ),
                      leading: CardUtils.getCardIcon(list[i].brand),
                      trailing: (list[i].isDefault)
                          ? Icon(
                              Icons.check_circle,
                              size: 32,
                              color: BmsColors.primaryForegroundColor,
                            )
                          : Container(
                              width: 32,
                            ),
                      onTap: () {
                        debugPrint('Tapped on ');
                      },
                    ),
                  ),
                );
              },
            ),
    

    您还应该使用FutureBuilder 进行异步调用以获取数据:

     FutureBuilder(
        future: _getDataFromDatabase(), //async function that returns a Future<Map<String, dynamic>>
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (!snapshot.hasData) {
            if (snapshot.connectionState == ConnectionState.done) {
              list = [];
            }
            return CircularProgressIndicator();
          }
    
          list = snapshot.data;
          return _buildScaffold(); //contains your ListView.builder
        });
    

    【讨论】:

    • 非常感谢您的反馈,我会尝试这些并进一步研究 FutureBuilder 和 ListView.builder 以便更好地理解。
    【解决方案2】:

    Brian 的回答有很多你应该考虑的事情。尽管我认为您的问题有一部分需要引起注意:

    当我热重载时,它只会在调试模式下加载动态小部件 应用程序。

    这几乎总是表明一旦数据发生变化,您就会错过 setState((){}) 调用。这意味着发生了更改,但在更改发生后尚未重建 UI。即使有了 Brian 的更改,您也没有调用 setState(尽管如果您只在页面加载时添加此数据一次,那么这不是什么大问题)。当然,请使用 Brian 对如何构建 UI 的建议。 ListView.builder 是满足这些类型需求的方法。我的回答是,当您对数据进行更改并且在您的 UI 中看不到任何更改时,需要考虑更多的事情。

    【讨论】:

      猜你喜欢
      • 2020-05-31
      • 1970-01-01
      • 2015-06-28
      • 1970-01-01
      • 2013-05-08
      • 1970-01-01
      • 2012-04-28
      • 2016-06-10
      • 1970-01-01
      相关资源
      最近更新 更多