Flutter小技巧|通过多样式Cell看断言

5,885 阅读2分钟

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战

Hi 👋

我的个人项目扫雷Elic 无尽天梯梦见账本隐私访问记录
类型游戏财务工具
AppStoreElicUmemi隐私访问记录

更多专栏:

Lawliet的独立开发碎碎念

Lawliet的iOS游园会

Lawliet的iOS底层实验室

Lawliet的iOS逆向实验室

Lawliet的刷题小本本

前言

我们在构建如微信联系人页类似的 Cell 时,主要有两种。一种是加载网络图片,用来现实我们的联系人;一种是本地图片,用来显示一些系统入口,如公众号等。那么如何优雅的完成这样对两种形式数据展示的 Cell 呢?借助这个场景,我们来了解一下 断言

10-01.png

不使用断言

这样的代码,并没有什么明显问题。

  • 普通联系人传入 avatarUrl 网络图片
  • 系统入口传入 assetName 资源名称
  • avatarUrl 和 assetName 都是可选字段,即均可为空

这样的隐患是无法保证至少有一个是有值的。下面我们使用断言进行优化,如果两者都为空就会抛出异常。

class _ContactCell extends StatelessWidget {
  const _ContactCell({
    required this.name,
    this.avatarUrl,
    this.assetName,
  });

  final String name;
  final String? avatarUrl;
  final String? assetName;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 60,
      color: Colors.white,
      child: Stack(
        children: [
          Row(
            children: [
              Row(
                children: [
                  const SizedBox(
                    width: 12,
                  ),
                  avatarUrl != null
                      ? Container(
                          width: 48,
                          height: 48,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(4),
                            image: DecorationImage(
                              image: NetworkImage(avatarUrl!),
                            ),
                          ),
                        )
                      : Container(),
                  assetName != null
                      ? Container(
                          width: 48,
                          height: 48,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(4),
                            image: DecorationImage(
                              image: AssetImage(assetName!),
                            ),
                          ),
                        )
                      : Container(),
                  const SizedBox(
                    width: 12,
                  ),
                  Text(
                    name,
                    style: const TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w500,
                    ),
                  ),
                ],
              ),
            ],
          ),
          Positioned(
            left: 50,
            bottom: 0,
            child: Container(
              height: 1,
              color: Colors.grey,
            ),
          ),
        ],
      ),
    );
  }
}

使用断言进行优化

这里在构造方法加了断言: assert((avatarUrl != null || assetName != null), '至少一张图片')

如果两者都为空,那么就会抛出如图异常:

10-02.png

class _ContactCell extends StatelessWidget {
  const _ContactCell({
    required this.name,
    this.avatarUrl,
    this.assetName,
  }) : assert((avatarUrl != null || assetName != null), '至少一张图片');

  final String name;
  final String? avatarUrl;
  final String? assetName;

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 60,
      color: Colors.white,
      child: Stack(
        children: [
          Row(
            children: [
              Row(
                children: [
                  const SizedBox(
                    width: 12,
                  ),
                  avatarUrl != null
                      ? Container(
                          width: 48,
                          height: 48,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(4),
                            image: DecorationImage(
                              image: NetworkImage(avatarUrl!),
                            ),
                          ),
                        )
                      : Container(),
                  assetName != null
                      ? Container(
                          width: 48,
                          height: 48,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(4),
                            image: DecorationImage(
                              image: AssetImage(assetName!),
                            ),
                          ),
                        )
                      : Container(),
                  const SizedBox(
                    width: 12,
                  ),
                  Text(
                    name,
                    style: const TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w500,
                    ),
                  ),
                ],
              ),
            ],
          ),
          Positioned(
            left: 50,
            bottom: 0,
            child: Container(
              height: 1,
              color: Colors.grey,
            ),
          ),
        ],
      ),
    );
  }
}