Flutter 中使用條件表達式的奇技淫巧

在工作中我們可能會寫出以下代碼:

class MyExampleState extends State<MyExample> {
  bool loading = false;
  Data? data;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: loading
          ? const CircularProgressIndicator()
          : (data == null ? const Text('error_area') : const Text('content_area')),
    );
  }
}

這樣的三元表達式看起來很丑理茎,如果條件再多點,就很難維護了管嬉。

如果你對 Dart 語言了解得比較深的話皂林,應該知道在 Dart 的集合中是可以使用 if、for 循環(huán)語法的蚯撩。這個特性是 Dart 專為 Flutter 定制的础倍,Dart 一直聲稱自己是一個為全平臺構(gòu)建快速應用的客戶端優(yōu)化的編程語言。后面我們有機會可以來仔細盤點一下 Dart 都為客戶端開發(fā)(主要是 Flutter)做了哪些優(yōu)化胎挎。

這種 if 和 for 語法標準的叫法是集合中的 if集合中的 for沟启。它們是 if 和 for 語句的閹割版。比如兩者都沒法使用花括號 {} 來把語句體包起來犹菇。后者你沒法使用 break德迹、continue。下面的示例幾乎展現(xiàn)了它們的全部語法:

List<Widget> widgets = [
  if (loading)
    const CircularProgressIndicator()
  else if (data == null)
    const Text('error_area')
  else
    const Text('content_area'),
  for (int i = 0; i < 10; i++) Text('item_$i')
];

集合中的 if集合中的 for相比第一個例子中的三元表達式要好多了揭芍,條件再多也會很清晰胳搞。很遺憾的是它只能在集合中使用,而在大量的場景下,方法的形參接收的是單一變量而非集合肌毅。能不能針對這類方法也用上集合中的 if集合中的 for呢筷转?答案是肯定的!看代碼:

class MyExampleState extends State<MyExample> {
  bool loading = false;
  Data? data;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: [
        if (loading)
          const CircularProgressIndicator()
        else if (data == null)
          const Text('error_area')
        else
          const Text('content_area')
      ][0],
    );
  }
}

盡管 body 只接收一個 Widget悬而,但我們構(gòu)造了一個集合呜舒,并將集合的第 0 個元素賦值給 body,而條件表達式的作用就是去生成第 0 個元素笨奠。是不是很 nice袭蝗?這種用法可以擴展到所有只接收單一參數(shù)而非集合的地方,比如 color般婆、width呻袭、height 的設置。

除了集合中的 if集合中的 for以外腺兴,2.3 版本的 Dart 還引入了 擴展操作符(...)和 空感知擴展操作符(...?),它們提供了一種將多個元素插入集合的簡潔方法廉侧,比如:

var list = [1, 2, 3];
var list2 = [0, ...list];
assert(list2.length == 4);

以往我們封裝的 buildXXX 方法只返回一個 Widget页响,有了這個特性以后,我們可以返回一個 List<Widget>段誊。并使用 ... 操作符將其添加到 children 列表中:

class MyExampleState extends State<MyExample> {
  bool loading = false;
  Data? data;

  List<Widget> buildTitleArea() {
    return [];
  }

  Widget buildBody() {
    return const Text('body_area');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ConstraintLayout(
        children: [
          ...buildTitleArea(),
          buildBody(),
        ],
      ),
    );
  }
}

結(jié)合集合中的 if闰蚕,我們可以實現(xiàn)對多個 Widget 的顯示、隱藏连舍。

以上所講的這些没陡,其實在 Flutter ConstraintLayout 中有更好的辦法,因為它創(chuàng)造性的支持了開放式語法(Open Grammar)索赏,你可以使用 Dart 的任何語法來組織子元素:

class OpenGrammarExample extends StatelessWidget {
  const OpenGrammarExample({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ConstraintLayout().open(() {
        if (DateTime.now().millisecond % 2 == 0) {
          Container(
            color: Colors.red,
          ).applyConstraint(
            size: 200,
            centerTo: parent,
          );
        } else {
          Container(
            color: Colors.yellow,
          ).applyConstraint(
            size: 200,
            centerTo: parent,
          );
        }

        for (int i = 0; i < 5; i++) {
          Row().open(() {
            for (int j = 0; j < 10; j++) {
              Text("$i x $j").enter();
              const SizedBox(
                width: 20,
              ).enter();
            }
          }).applyConstraint(
            height: 100,
            left: parent.left.margin(100),
            top: i == 0 ? parent.top : sId(-1).bottom,
          );
        }

        int i = 0;
        while (i < 100) {
          Text("$i").applyConstraint(
            left: parent.left,
            top: i == 0 ? parent.top : sId(-1).bottom,
          );
          i++;
        }
      }),
    );
  }
}

是不是很 nice盼玄?

好了,這篇文章就到這里潜腻,歡迎在評論區(qū)交流埃儿,我是中國第一位 Android & Flutter 雙料 GDFE,關注我的公眾號:FlutterFirst融涣,帶你起飛童番!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市威鹿,隨后出現(xiàn)的幾起案子剃斧,更是在濱河造成了極大的恐慌,老刑警劉巖忽你,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件幼东,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機筋粗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門策橘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人娜亿,你說我怎么就攤上這事丽已。” “怎么了买决?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵沛婴,是天一觀的道長。 經(jīng)常有香客問我督赤,道長嘁灯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任躲舌,我火速辦了婚禮丑婿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘没卸。我一直安慰自己羹奉,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布约计。 她就那樣靜靜地躺著诀拭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪煤蚌。 梳的紋絲不亂的頭發(fā)上耕挨,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音尉桩,去河邊找鬼筒占。 笑死,一個胖子當著我的面吹牛蜘犁,可吹牛的內(nèi)容都是我干的赋铝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼沽瘦,長吁一口氣:“原來是場噩夢啊……” “哼革骨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起析恋,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤良哲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后助隧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體筑凫,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡滑沧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了巍实。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滓技。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖棚潦,靈堂內(nèi)的尸體忽然破棺而出令漂,到底是詐尸還是另有隱情,我是刑警寧澤丸边,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布叠必,位于F島的核電站,受9級特大地震影響妹窖,放射性物質(zhì)發(fā)生泄漏纬朝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一骄呼、第九天 我趴在偏房一處隱蔽的房頂上張望共苛。 院中可真熱鬧,春花似錦蜓萄、人聲如沸隅茎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至摊阀,卻和暖如春耻蛇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胞此。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工臣咖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人漱牵。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓夺蛇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親酣胀。 傳聞我的和親對象是個殘疾皇子刁赦,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容