Flutter Provider - 重建列表项而不是列表视图

2023-12-29

我正在使用 Provider 包来管理我的应用程序业务逻辑,但我遇到了一个问题,即正在重建整个 ListView 而不是单个 ListTile。下面的 UI 可让您更好地理解:

目前,如果我滚动到列表底部,点击最后一项的复选框,我看不到复选框切换的动画,并且滚动跳到屏幕顶部,因为整个小部件已重建。如何使用 Provider 以便仅重建单个 ListTile 而不是列表中的每个项目?这是一些相关代码:


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Checklist',
        theme: ThemeData(
          brightness: Brightness.light,
          primaryColor: Colors.indigo[500],
          accentColor: Colors.amber[500],
        ),
        home: ChecklistHomeScreen(),
      ),
      providers: [
        ChangeNotifierProvider(
          create: (ctx) => ChecklistsProvider(),
        ),
      ],
    );
  }
}
class ChecklistHomeScreen extends StatefulWidget {
  @override
  _ChecklistHomeScreenState createState() => _ChecklistHomeScreenState();
}

class _ChecklistHomeScreenState extends State<ChecklistHomeScreen> {
  void createList(BuildContext context, String listName) {
    if (listName.isNotEmpty) {
      Provider.of<ChecklistsProvider>(context).addChecklist(listName);
    }
  }

  @override
  Widget build(BuildContext context) {
    final _checklists = Provider.of<ChecklistsProvider>(context).checklists;
    final _scaffoldKey = GlobalKey<ScaffoldState>();
    ScrollController _scrollController =
        PrimaryScrollController.of(context) ?? ScrollController();

    return Scaffold(
      key: _scaffoldKey,
      body: CustomScrollView(
        controller: _scrollController,
        slivers: <Widget>[
          SliverAppBar(
            floating: true,
            pinned: false,
            title: Text('Your Lists'),
            centerTitle: true,
            actions: <Widget>[
              PopupMenuButton(
                itemBuilder: (ctx) => null,
              ),
            ],
          ),
          ReorderableSliverList(
            delegate: ReorderableSliverChildBuilderDelegate(
              (ctx, i) => _buildListItem(_checklists[i], i),
              childCount: _checklists.length,
            ),
            onReorder: (int oldIndex, int newIndex) {
              setState(() {
                final checklist = _checklists.removeAt(oldIndex);
                _checklists.insert(newIndex, checklist);
              });
            },
          ),
        ],
      ),
      drawer: Drawer(
        child: null,
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: null,
      ),
    );
  }

  Widget _buildListItem(Checklist list, int listIndex) {
    return Dismissible(
      key: ObjectKey(list.id),
      direction: DismissDirection.endToStart,
      background: Card(
        elevation: 0,
        child: Container(
          alignment: AlignmentDirectional.centerEnd,
          color: Theme.of(context).accentColor,
          child: Padding(
            padding: EdgeInsets.fromLTRB(0.0, 0.0, 10.0, 0.0),
            child: Icon(
              Icons.delete,
              color: Colors.white,
            ),
          ),
        ),
      ),
      child: Card(
        child: ListTile(
          onTap: null,
          title: Text(list.name),
          leading: Checkbox(
            value: list.completed,
            onChanged: (value) {
              Provider.of<ChecklistsProvider>(context)
                  .toggleCompletedStatus(list.id, list.completed);
            },
          ),
          trailing: IconButton(
            icon: Icon(Icons.more_vert),
            onPressed: null,
          ),
        ),
      ),
      onDismissed: (direction) {
        _onDeleteList(list, listIndex);
      },
    );
  }

  void _onDeleteList(Checklist list, int listIndex) {
    Scaffold.of(context).removeCurrentSnackBar();
    Scaffold.of(context).showSnackBar(
      SnackBar(
        action: SnackBarAction(
          label: 'UNDO',
          onPressed: () {
            Provider.of<ChecklistsProvider>(context)
                .undoDeleteChecklist(list, listIndex);
          },
        ),
        content: Text(
          'List deleted',
          style: TextStyle(color: Theme.of(context).accentColor),
        ),
      ),
    );
  }
}
class ChecklistsProvider with ChangeNotifier {
  final ChecklistRepository _repository = ChecklistRepository(); //singleton

  UnmodifiableListView<Checklist> get checklists => UnmodifiableListView(_repository.getChecklists());

  void addChecklist(String name) {
    _repository.addChecklist(name);
    notifyListeners();
  }

  void deleteChecklist(int id) {
    _repository.deleteChecklist(id);
    notifyListeners();
  }

  void toggleCompletedStatus(int id, bool completed) {
    final list = checklists.firstWhere((c) => c.id == id);
    if(list != null) {
      list.completed = completed;
      _repository.updateChecklist(list);
      notifyListeners();
    }
  }
}

我应该说我理解为什么这是当前的行为,我只是不确定确保仅重建我想要更新的列表项而不是整个屏幕的正确方法。 我也读过Consumer但我不确定如何将其融入我的实施中。


消费者本质上允许您使用对更改通知程序所做的任何更改。最佳实践是将 Consumer 尽可能深入地嵌入到您的构建方法中。这样,只有包装的小部件才会被重新构建。这篇文档很好地解释了这一点:https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

尝试将您的 CheckBox 小部件包装在 Consumer 小部件中。仅应重建复选框。

Consumer<ChecklistsProvider>(
  builder: (context, provider, _) {
    return Checkbox(
      value: list.completed,
      onChanged: (value) {
        provider.toggleCompletedStatus(list.id, list.completed);
      },
    );
  },
),

如果您希望重新构建 ListTile 和 CheckBox,只需将 ListTile 包装在 Consumer 中即可

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flutter Provider - 重建列表项而不是列表视图 的相关文章

随机推荐

  • 如何登录 Google Cloud 上的 phpmyadmin

    我设置了 WordPress 1 Click Google Cloud 自动为我创建了一个用户 我没有找到 phpmyadmin 密码所在的任何地方 我怎样才能抓住它 首先 当您部署一键安装时 您需要确保选中 安装 phpMyAdmin 我
  • 使用 Android USB Host API 读取我的 USB 游戏控制器/或其他 USB 设备数据

    我正在尝试使用 Android USB Host API 读取我的 USB 游戏控制器数据 一旦我让它工作 我将连接其他设备进行测试 我的游戏控制器使用 OTG 线连接到我的 Android 手机 我现在能够获取设备 端点信息 但我不知道如
  • 配置中的属性占位符

    在 xml 上下文中使用 Spring 我们可以像这样简单地加载属性
  • r 中带有 Plot_ly 的 3D 表面,带有 x、y、z 坐标

    I am trying to use 3D surface plots to analyze the stability of outcomes as a function of inputs z is my outcome and x a
  • 如何从“带有时区的时间戳”列读取时区?

    我无法找到读取 PostgreSQL 类型列中时区值的方法带时区的时间戳 JDBC提供方法java sql ResultSet getTimestamp int java util Calendar 但我必须提供我自己的日历 我看不出有什么
  • 已弃用的 AudioManager.isWiredHeadsetOn 的替代方案?

    方法AudioManager isWiredHeadsetOn http developer android com reference android media AudioManager html isWiredHeadsetOn 28
  • 我已经成功安装了magento2但是有很多js错误

    我已经成功安装了magento2 但是有很多js错误 当通过 firebug 查看控制台日志时 它显示了很多错误 并且还有其他内容需要为 magento css 和 js 配置吗 尝试以下 使 bin magento 可执行 chmod x
  • sqlite3 - 如何使用 .databases 命令列出数据库名称?

    我是 Rails 和 SQLite 的新手 这是我的场景 我有sqlite3安装在我的 Windows Vista 计算机上 博客应用程序代码也已在以下位置实现 c rails blog 我调出命令提示符并直接进入c rails blog
  • ScrollView 内的 ForEach 不占用整个宽度

    我正在尝试使用 SwiftUI 重新创建当前应用程序的 UI 但这比我最初要困难得多 我想要实现类似卡片的单元格 背后有一些背景 我找到List至少目前还不支持这一点 List是如此有限 它不允许您移除电池分隔符 所以我搬到了ForEach
  • 检查 Jenkins 管道中是否存在插件 (Groovy)

    我想在我的管道中使用 Slack 通知插件 这非常简单 slackSend color danger message Everything broke 但是 如果 slackSend 不存在 我不希望构建中断 有没有办法先检查一下 你也许可
  • 使用 ggplot2 将每个第 N 轴标签加粗

    是否可以使用 ggplot2 将轴上的第 N 个刻度设为粗体 我只想将轴标记为粗体 小线 而不是文本 在绘图中显示每日数据时 这对于突出显示每 7 个刻度非常有用 我想保留每一天的刻度线 我无法找到有关此主题的任何内容 任何帮助将不胜感激
  • Python:将数据类型从整数更改为浮点时出现内存错误

    我有一个大小为 13000 300000 的数组 其中填充了从 0 到 255 的整数 我想将它们的数据类型从整数更改为浮点 就好像数据是 numpy 数组一样 data astype float 当将其数据类型从整数更改为浮点时 它显示内
  • Git 终端使用旧帐户将文件推送到我的新 github 帐户[重复]

    这个问题在这里已经有答案了 我最近创建了一个新的 github 帐户 当我尝试通过 git 终端将一些文件推送到我的新帐户的存储库中时 它告诉我无权访问新帐户 因此 我手动删除了之前帐户的旧凭据 并通过 git 终端保存了新凭据 现在 它将
  • ASP.NET MVC 子字符串帮助

    我有一个 ASP NET MVC 应用程序 用于显示新闻文章 对于主要段落 我有一个截断和 HTML 标签剥离器 例如 p p 这两个函数来自扩展 如下所示 public static string RemoveHTMLTags this
  • rsync 在传输过程中突然无限期挂起

    在过去的几年里 我一直在使用 rsync 单行程序将 Mac Mini 桌面 OSX 10 9 2 5 GHz i5 4 GB RAM 上的重要文件夹备份到 FreeNAS 盒子 0 7 2 Sabanda 修订版 5266 Pentium
  • 获取缩放散点图中的面积或元素

    我有以下问题 我想放大散点图 然后选择所有显示的元素 以某种方式获得放大散点图中的显示区域就足够了 从该区域的范围我可以确定哪些元素显示在该区域中 哪些不显示 edit 找到解决方案 实现 AxisChangeListener 接口 imp
  • Pandas:如何将系列的多重索引折叠为日期时间索引?

    作为后续Pandas groupby 按学期分组 https stackoverflow com questions 51854809 pandas groupby group by semester我需要将系列的多重索引折叠为日期时间索引
  • 如何在 ASP.Net MVC for Mono 中使用异步

    我正在使用 Visual Studio 2017 for Mac 在 Mono 中创建 ASP Net MVC 项目 我添加了基本的控制器 视图 模型等 并且运行良好 但是 一旦使 Index 方法异步 我就会收到以下错误 System I
  • 如何根据第三个变量对分散标记进行着色

    我想制作一个散点图 使用 matplotlib 其中点根据第三个变量进行着色 我已经非常接近这个了 plt scatter w M c p marker s 其中 w 和 M 是数据点 p 是我想要着色的变量 不过我想用灰度而不是彩色来做
  • Flutter Provider - 重建列表项而不是列表视图

    我正在使用 Provider 包来管理我的应用程序业务逻辑 但我遇到了一个问题 即正在重建整个 ListView 而不是单个 ListTile 下面的 UI 可让您更好地理解 目前 如果我滚动到列表底部 点击最后一项的复选框 我看不到复选框