【问题标题】:Prevent ListView.Builder rebuild for a particular ListItem Change in FutureBuilder防止为 FutureBuilder 中的特定 ListItem 更改重建 ListView.Builder
【发布时间】:2021-10-01 17:42:20
【问题描述】:

我正在从 sqflite 数据库中查询数据并使用 futurebuilder 来显示刷新图标。一旦通过 snapshot.connectionState == ConnectionState.done 检索到数据,我将调用 ListView.builder 方法来显示数据。我在显示的每个列表项中也有一个图标。单击该项目后,我将切换数据库中的列值。因为我还需要在每次点击时切换 ui 中的图标。为此,在更新数据库后,我调用了 setstate。这会切换 ui 中的图标,但由于 setstate,整个项目列表正在重建。我怎样才能避免这种情况?我只想改变那个特定列表项的图标。 Provider 是实现这一目标的推荐方法吗?

  class _HomeState extends State<Home> {
  final _dbHelper = DatabaseHelper.instance;
  
  
    Future<int> _toggleFavourite(int id, int value) async {
    return await _dbHelper.updateFavourite(id, value);- //toogles the column value in db
  }
  
  
   @override
  Widget build(BuildContext context) {
    return Scaffold(
   body: FutureBuilder(
              future: _dbHelper.queryAllRows(),//Get all rows from db
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  final _allRows = snapshot.data as List<Map<String, dynamic>>;
                  _codes.clear();
                  _allRows.forEach((row) => _codes.add(Code.fromMap(row)));
                  
                   return SafeArea(
                    child: Column(
                      children: [
                        Expanded(
                          child:ListView.builder(
                                  padding: const EdgeInsets.all(8),
                                  itemCount: _codes.length,
                                  itemBuilder:
                                      (BuildContext context, int index) {
                                    return InkWell(
                                        onTap: () {
                                                                                 },
                                        child: Card(
                                         
                                            child: ListTile(
                                           
                                              title: Text(
                                                _codes[index].code,
                                                maxLines: 1,
                                                overflow: TextOverflow.ellipsis,
                                                softWrap: false,
                                              ),
                                            trailing: SizedBox(
                                                width: 100,
                                                child: Row(
                                                  children: [
                                                    IconButton(
                                                        onPressed: () {
                                                          _toggleFavourite(
                                                                  _codes[index]
                                                                      .id,
                                                                  _codes[index]
                                                                              .favourite ==
                                                                          1
                                                                      ? 0
                                                                      : 1)
                                                              .then(
                                                                  (affectedRows) {
                                                            if (affectedRows >
                                                                0) {
                                                              setState(() {});//Rebuilds all the listitems :(
                                                            }
                                                            
                                                          });
                                                        },
                                                        icon: Icon(
                                                          _codes[index]
                                                                      .favourite ==
                                                                  1
                                                              ? Icons.favorite
                                                              : Icons
                                                                  .favorite_border_outlined,
                                                          size: 35,
                                                        )),
                                                        
                                                        .........
                                                    
                                                    
                                                    

【问题讨论】:

  • 如果你想阻止任何东西重建,你应该使用'const'关键字。但是,如果您共享代码会更好。
  • 我怀疑更新唯一的图标是可能的!如果它正在重建完整列表,你会感到困扰吗?

标签: flutter


【解决方案1】:

ListView 项目创建一个单独的小部件,并在该新小部件中拥有数据库和切换功能。

另外,Flutter 始终建议使用 const 关键字,该关键字不会为特定的小部件再次重建。

编辑:

创建单独的StatefulWidget,因为您必须切换功能

例如:在新的 StatefulWidget 小部件中包含 InkWell 整个块,并在那里实现您的实现

   InkWell(
          onTap: () {
                                                                                 
          },
     child: Card( 
          ///......
          )

否则,如果 FutureBuilder 多次触发,请参考博客 https://medium.com/flutterworld/why-future-builder-called-multiple-times-9efeeaf38ba2

【讨论】:

  • 感谢您的回复。您能否请展示 const 对上述特定代码的使用,因为我很困惑将它放在哪里。另外,当您说要创建单独的小部件时,为 ListItem 而不是 ListView 创建有状态小部件会更好吗?
  • @user24826:我编辑了答案,请看一下。希望它对你有用。
  • 谢谢,将 ListItem 放入单独的有状态小部件解决了它。
  • @user24826:您能否接受并投票赞成答案
  • 完成。还只是想补充一点,我在stackoverflow.com/questions/52021205/… 找到了我实际问题的真正答案。基本上我不应该直接在 Futurebuilder 中加载未来。这会导致每次重新加载。相反,future 应该在 initstate 中加载。我改变了我的方法,因为为 ListItem 创建单独的小部件暂时解决了它,因为我在其他地方进行一些更新时又开始遇到同样的问题。
猜你喜欢
  • 2022-10-19
  • 2021-01-07
  • 2020-07-04
  • 1970-01-01
  • 2023-03-11
  • 2020-05-25
  • 2019-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多