Flutter入門-03-封裝簡單復(fù)用組件

前言

??首先我們知道Flutter的語法是嵌套型的,這種語法的最直觀的感受就是代碼多,嵌套層次深的話可能導(dǎo)致代碼閱讀困難,其實(shí),這也是Flutter的一項(xiàng)不完美的地方吧。

正文

??面對這個問題,我們可以采用代碼抽取,復(fù)用的方式來減少在一個文件中堆疊大量代碼;采用這種方式的好處如下:

  • 減少了使用處代碼的代碼量和層級,代碼精簡直觀
  • 抽取出的代碼可以多處復(fù)用,不限于當(dāng)前頁面,方便靈活拓展
  • 減少了代碼量的同時,也方便了后續(xù)維護(hù)者的閱讀與編寫,便于維護(hù)

一:代碼抽取

??在日常的開發(fā)中,我們首先會拿到UI的設(shè)計稿,在腦子里已經(jīng)排版布局,然后就瘋狂的碼代碼。例如UI小姐姐拿出了下面常用設(shè)計稿


我的
  1. 經(jīng)過分析,這是一個除了圖標(biāo)和文字,其他都一樣的組件
  2. 開始編寫其中一條的代碼,比如我的訂單
  3. 寫完一條后后粘貼復(fù)制,修改成其他剩余的icon和文字就搞定了

那我就直接拿出某一條代碼,這是從Android studio里直接copy的,行數(shù)我看了下是41行,具體原始代碼如下:

GestureDetector(
              child: Container(
                  color: Color(0xffffffff),
                  padding: EdgeInsets.only(left: 20, right: 16),
                  child: SizedBox(
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: <Widget>[
                        Wrap(
                          runAlignment: WrapAlignment.center,
                          crossAxisAlignment: WrapCrossAlignment.center,
                          children: <Widget>[
                            Image.asset(
                              "resource/imgs/icon_my_card.png",
                              width: 18,
                              height: 18,
                              fit: BoxFit.contain,
                            ),
                            Padding(
                                padding: EdgeInsetsDirectional.only(start: 22)),
                            Text("銀行卡01"),
                          ],
                        ),
                        Wrap(
                          runAlignment: WrapAlignment.center,
                          crossAxisAlignment: WrapCrossAlignment.center,
                          children: <Widget>[
                            Text(""),
                            Padding(
                              padding: EdgeInsetsDirectional.only(start: 10),
                              child:
                                  Image.asset("resource/imgs/arrow_right.png"),
                            )
                          ],
                        ),
                      ],
                    ),
                    height: 48,
                  )),
              onTap: () {},
            )

??按照我們原來的偷懶計劃,直接粘貼復(fù)制,一頓操作后發(fā)現(xiàn)近300行代碼,心中竊喜(這下統(tǒng)計代碼量,老子吊打一切,- _-)。當(dāng)然開玩笑,我們寫代碼不是為了多,而是完成一個功能,使用的代碼越少越好。

二:改造代碼,多處復(fù)用

??我們上面發(fā)現(xiàn),只是實(shí)現(xiàn)了7個相同的item,沒有優(yōu)化的情況下就編寫了200多行代碼,這實(shí)在是太多了,看起來也是眼花繚亂的。不行,我們作為有責(zé)任感,有逼格的程序員怎么能看的下去呢,我們需要對這坨代碼進(jìn)行優(yōu)化,大腦在思考:

1. 其實(shí)大多數(shù)代碼都一樣,只是圖標(biāo)和文字不同
2. 是否能夠抽取公共部分,把變量部分暴露出來給用戶自己動態(tài)傳遞呢

答案當(dāng)然是可以的,且思路也是正確的。那么我們用什么來存儲這些公共部分呢,有兩種方式:

1. 繼承statelessWidget或者statefulWidget,重新渲染公共部分
2. 直接寫個公共方法,在return里直接返回公共部分組件

兩種方式都是可以的,看需求而定;如果你的公共部分不需要獨(dú)立的動態(tài)渲染,只是提供靜態(tài)的公共組件,那直接選用第二種將更方便;這里我們看,我們的公共部分,只是靜態(tài)的顯示,不涉及動態(tài)變化的東西,我們就直接用第二種,抽取的過程我就不多說了,下面看抽取出來的代碼:

///通用item左右都帶有有個icon和text的通用item,常用于我的頁面等item條目
///
///[iconLeft] 左邊icon的widget
///
///[textLeft] 左邊文本的Widget
///
///[iconRight] 右邊icon的widget
///
///[textRight] 右邊文本的Widget
///
///[heightItem] item高度
///
///[paddingLeftRight] 左邊Image距離右邊文本的間距
///
///[paddingRightLeft] 右邊Image距離左邊文本的間距
///
///[importance] 左側(cè)文本是否顯示必填*號
///
///[onPress] item點(diǎn)擊事件函數(shù)回調(diào)
iconTextItem(
    {Widget iconLeft,
    Widget iconRight,
    double heightItem = 50,
    double paddingLeftRight = 8,
    double paddingRightLeft = 15,
    importance = false,
    Color backgroundColor,
    double leftPadding,
    double rightPadding,
    @required Widget textLeft,
    Widget textRight,
    VoidCallback onPress,
    Key key}) {
  return GestureDetector(
    child: Container(
        key: key,
        color: backgroundColor ?? Color(0xffffffff),
        padding:
            EdgeInsets.only(left: leftPadding ?? 0, right: rightPadding ?? 0),
        child: SizedBox(
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Wrap(
                runAlignment: WrapAlignment.center,
                crossAxisAlignment: WrapCrossAlignment.center,
                children: <Widget>[
                  iconLeft ?? Text(""),
                  Padding(
                      padding: EdgeInsetsDirectional.only(
                          start: iconLeft != null ? paddingLeftRight : 0),
                      child:
                          importance ? _getImportanceText(textLeft) : textLeft),
                ],
              ),
              Wrap(
                runAlignment: WrapAlignment.center,
                crossAxisAlignment: WrapCrossAlignment.center,
                children: <Widget>[
                  textRight ?? Text(""),
                  Padding(
                    padding:
                        EdgeInsetsDirectional.only(start: paddingRightLeft),
                    child: iconRight ??
                        Image.asset("resource/imgs/arrow_right.png"),
                  )
                ],
              ),
            ],
          ),
          height: heightItem,
        )),
    onTap: onPress,
  );
}

/// 返回帶有必填*的文本,*號默認(rèn)紅色
_getImportanceText(Text text, {Color color}) {
  assert(text != null);
  return Wrap(
    crossAxisAlignment: WrapCrossAlignment.center,
    children: <Widget>[
      text,
      Text(
        "*",
        style: TextStyle(color: color ?? colorRed23681731, fontSize: 15),
      ),
    ],
  );
}

代碼行數(shù)為59行,為啥反而多了呢,因?yàn)檫@里我又兼容了如下的設(shè)計稿,通過傳入?yún)?shù)可以控制紅色的*是否顯示,也就是達(dá)到了是否必須的設(shè)計效果


必填項(xiàng)

那既然我們都封裝好了,如何在代碼里使用呢,使用方式在目標(biāo)頁面中,直接放入即可,具體引入處代碼如下:

iconTextItem(
              onPress: () {
                print("我的銀行卡");
                Navigator.pushNamed(context, "/mybankcard");
              },
              leftPadding: 20,
              rightPadding: 14,
//            backgroundColor: Colors.greenAccent,
              paddingLeftRight: 22,
              iconLeft: Image.asset(
                "resource/imgs/icon_my_card.png",
                width: 18,
                height: 18,
                fit: BoxFit.contain,
              ),
              textLeft: Text(
                "我的銀行卡",
                style: TextStyle(color: colorBlackFF444C63, fontSize: 15),
              ),
            )

我們把圖標(biāo)和文字聲明在方法參數(shù)中,同時提供部分默認(rèn)值,使用處傳參即可。我復(fù)制過來是19行,原來41行,當(dāng)前文件節(jié)省了21行,不僅如此還減少了層疊情況,看起來更清晰了?,F(xiàn)在完成第一個設(shè)計稿只需要19*7=133行,比原來(42*7=294)優(yōu)化了161行,這種效果還是看得見的

總結(jié):

??本片文章主要介紹了通過方法來抽取公共部分的代碼加以復(fù)用,方便日后的維護(hù)拓展。這里還有個自己輕度封裝簡潔的庫,是一個左右widget的package,同樣可以達(dá)到上述效果,給用戶留了更大的自定義空間,大家有興趣的可以了解使用支持下

上一篇:Flutter入門-02-Dart語言簡講
下一篇:Android開發(fā)之WebView(一)配置&小技巧

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容