首页 > 解决方案 > 防止为 FutureBuilder 中的特定 ListItem 更改重建 ListView.Builder

问题描述

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

  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,
                                                        )),
                                                        
                                                        .........
                                                    
                                                    
                                                    

标签: flutter

解决方案


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

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

编辑:

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

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

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

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


推荐阅读