Flutter 疑难杂症(二)

1、空字符占位(\u3000 \u0020)使用

body: Container(
        width: double.infinity,
        height: double.infinity,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text('a\u0020b\u0020cdefg'),
            Text('abcdefgh'),
            Text('三\u0020\u0020字\u0020\u0020字'),
            Text('四字字字'),
            Text('二\u3000\u3000字'),
            Row(
              children: [
                Text('三\u0020\u0020字\u0020\u0020字'),
                Expanded(
                  child: SizedBox(),
                )
              ],
            )
          ],
        ),
      ),

效果如下:


image.png

从结果可知,\u3000相当于占用一个中文字符,\u0020相当于占用1/4个中文字符,我们可以通过\u3000或\u0020来对齐表单左边文案,注意:字体样式要一致才有效;

2、数组、列表等自带查找匹配方法

iterator.dart

  /**
   * Returns the first element that satisfies the given predicate [test].
   *
   * Iterates through elements and returns the first to satisfy [test].
   *
   * If no element satisfies [test], the result of invoking the [orElse]
   * function is returned.
   * If [orElse] is omitted, it defaults to throwing a [StateError].
   */
  E firstWhere(bool test(E element), {E orElse()}) {
    for (E element in this) {
      if (test(element)) return element;
    }
    if (orElse != null) return orElse();
    throw IterableElementError.noElement();
  }

  /**
   * Returns the last element that satisfies the given predicate [test].
   *
   * An iterable that can access its elements directly may check its
   * elements in any order (for example a list starts by checking the
   * last element and then moves towards the start of the list).
   * The default implementation iterates elements in iteration order,
   * checks `test(element)` for each,
   * and finally returns that last one that matched.
   *
   * If no element satisfies [test], the result of invoking the [orElse]
   * function is returned.
   * If [orElse] is omitted, it defaults to throwing a [StateError].
   */
  E lastWhere(bool test(E element), {E orElse()}) {
    E result;
    bool foundMatching = false;
    for (E element in this) {
      if (test(element)) {
        result = element;
        foundMatching = true;
      }
    }
    if (foundMatching) return result;
    if (orElse != null) return orElse();
    throw IterableElementError.noElement();
  }

  /**
   * Returns the single element that satisfies [test].
   *
   * Checks elements to see if `test(element)` returns true.
   * If exactly one element satisfies [test], that element is returned.
   * If more than one matching element is found, throws [StateError].
   * If no matching element is found, returns the result of [orElse].
   * If [orElse] is omitted, it defaults to throwing a [StateError].
   */
  E singleWhere(bool test(E element), {E orElse()}) {
    E result;
    bool foundMatching = false;
    for (E element in this) {
      if (test(element)) {
        if (foundMatching) {
          throw IterableElementError.tooMany();
        }
        result = element;
        foundMatching = true;
      }
    }
    if (foundMatching) return result;
    if (orElse != null) return orElse();
    throw IterableElementError.noElement();
  }

方法说明:
firstWhere主要是用于筛选顺序第一个符合条件的元素,可能存在多个符合条件元素;
lastWhere主要是用于筛选顺序最后一个符合条件的元素,可能存在多个符合条件元素;
singleWhere主要是用于筛选顺序唯一一个符合条件的元素;

参数说明:
bool test(E element) :查找条件匹配方法,传子元素,匹配返回true;
E orElse():查找不到时,执行的方法,一般返回null;
返回值:返回匹配的子元素或orElse的返回值,一般通过自定义orElse中的返回值来判断是否查找到匹配条件的元素;

使用例子:

   var numbers = <int>[0, 3, 1, 2, 7, 12, 2, 4];
   //注意: 如果没有找到,执行orElse代码块,可返回一个指定的默认值-1
   print(numbers.firstWhere((num) => num == 5, orElse: () => -1)); 
   //注意: 如果没有找到,执行orElse代码块,可返回一个指定的默认值-1
   print(numbers.lastWhere((num) => num == 2, orElse: () => -1)); 
   //注意: 如果没有找到,执行orElse代码块,可返回一个指定的默认值, 
   //前提是集合中只有一个符合条件的元素, 否则就会抛出异常
   print(numbers.singleWhere((num) => num == 4, orElse: () => -1));

使用坑:

  • E orElse()虽然是一个可选参数,但如果找不到匹配的,会直接抛出异常,所以orElse参数必须实现;

  • singleWhere慎用,因为singleWhere必须集合中只有一个符合条件的元素, 否则就会抛出异常;同时,在查找条件要求不高时,推荐使用firstWhere,因为firstWhere查找到就返回结果,而singleWhere需要所有元素都要查找才结束,firstWhere效率更高;

3、按条件引入库

语法:

import <文件> if(<条件>) <文件>  as <别名>

例子:

import '_network_image_io.dart'
  if (dart.library.html) '_network_image_web.dart' as network_image;

说明:
条件参数:一般为不同平台(android/ios/桌面/web)加载的不同的处理程序(我支持您编写此库);
使用场景:不同平台(android/ios/桌面/web)兼容开发;

4、factory工厂构造方法

以NetworkImage为例:

Image(
        image: NetworkImage(imgUrl), 

一般NetworkImage使用如上,看下NetworkImage源码,如下:
image_provider.dart

import '_network_image_io.dart'
  if (dart.library.html) '_network_image_web.dart' as network_image;

abstract class NetworkImage extends ImageProvider<NetworkImage> {
 
  const factory NetworkImage(String url, { double scale, Map<String, String> headers }) = network_image.NetworkImage;
  ...
 
}

NetworkImage是一个抽象类,为什么可以实例化?我们注意到NetworkImage的构造方法是一个工厂构造方法,它其实实例化的是它的子类,如下:
_network_image_io.dart

import 'image_provider.dart' as image_provider;

class NetworkImage extends image_provider.ImageProvider<image_provider.NetworkImage> implements image_provider.NetworkImage {
 
  const NetworkImage(this.url, { this.scale = 1.0, this.headers });
  ...

_network_image_web.dart

import 'image_provider.dart' as image_provider;
class NetworkImage
    extends image_provider.ImageProvider<image_provider.NetworkImage>
    implements image_provider.NetworkImage {

  const NetworkImage(this.url, {this.scale = 1.0, this.headers});
  ...

上面两个分别是对应移动和web平台NetworkImage的实现类,也就是NetworkImage的子类,并且外部不可访问;
上面的代码比较绕,需要细心看,再理解下factory就很容易懂了

工厂构造方法:

  • 使用 factory 关键字来定义构造方法;
  • 构造方法返回对象;
  • 构造方法可能从缓存中获取一个实例并返回,或者 返回一个子类型的实例;

5、网络请求数据解析坑

class TestModel {
  double doubleValue;

  TestModel({this.doubleValue});

  TestModel.fromJson(Map<String, dynamic> json) {
    doubleValue = json['DoubleValue'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['DoubleValue'] = this.doubleValue;
    return data;
  }
}

一般我们用xx.fromJson的方法来解析网络请求数据,如果后台数据doubleValue返回0,就会报type 'int' is not a subtype of type ‘double'的错误

解决:
将doubleValue定义为dynamic类型,如下:

class TestModel {
  dynamic doubleValue;

  TestModel({this.doubleValue});

  TestModel.fromJson(Map<String, dynamic> json) {
    doubleValue = json['DoubleValue'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['DoubleValue'] = this.doubleValue;
    return data;
  }
}

注意:

  • 展示时用doubleValue.toString()
  • double类型的数据用toString()可能会出现小数点位数不符合要求的,需要将toString()换成toStringAsFixed(小数点位数)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354