前言
??首先我們知道Flutter的語法是嵌套型的丈氓,這種語法的最直觀的感受就是代碼多桨嫁,嵌套層次深的話可能導(dǎo)致代碼閱讀困難贰军,其實玻蝌,這也是Flutter的一項不完美的地方吧。
正文
??面對這個問題谓形,我們可以采用代碼抽取灶伊,復(fù)用的方式來減少在一個文件中堆疊大量代碼;采用這種方式的好處如下:
- 減少了使用處代碼的代碼量和層級寒跳,代碼精簡直觀
- 抽取出的代碼可以多處復(fù)用,不限于當(dāng)前頁面竹椒,方便靈活拓展
- 減少了代碼量的同時童太,也方便了后續(xù)維護者的閱讀與編寫,便于維護
一:代碼抽取
??在日常的開發(fā)中胸完,我們首先會拿到UI的設(shè)計稿书释,在腦子里已經(jīng)排版布局,然后就瘋狂的碼代碼赊窥。例如UI小姐姐拿出了下面常用設(shè)計稿
- 經(jīng)過分析爆惧,這是一個除了圖標和文字,其他都一樣的組件
- 開始編寫其中一條的代碼锨能,比如我的訂單
- 寫完一條后后粘貼復(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)砸泛,只是實現(xiàn)了7個相同的item十籍,沒有優(yōu)化的情況下就編寫了200多行代碼,這實在是太多了唇礁,看起來也是眼花繚亂的勾栗。不行,我們作為有責(zé)任感盏筐,有逼格的程序員怎么能看的下去呢围俘,我們需要對這坨代碼進行優(yōu)化,大腦在思考:
1. 其實大多數(shù)代碼都一樣琢融,只是圖標和文字不同
2. 是否能夠抽取公共部分界牡,把變量部分暴露出來給用戶自己動態(tài)傳遞呢
答案當(dāng)然是可以的,且思路也是正確的宿亡。那么我們用什么來存儲這些公共部分呢纳令,有兩種方式:
1. 繼承statelessWidget或者statefulWidget挽荠,重新渲染公共部分
2. 直接寫個公共方法平绩,在return里直接返回公共部分組件
兩種方式都是可以的圈匆,看需求而定;如果你的公共部分不需要獨立的動態(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點擊事件函數(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,
);
}
/// 返回帶有必填*的文本少孝,*號默認紅色
_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行,為啥反而多了呢袁翁,因為這里我又兼容了如下的設(shè)計稿柴底,通過傳入?yún)?shù)可以控制紅色的*是否顯示粱胜,也就是達到了是否必須的設(shè)計效果
那既然我們都封裝好了焙压,如何在代碼里使用呢,使用方式在目標頁面中涯曲,直接放入即可,具體引入處代碼如下:
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),
),
)
我們把圖標和文字聲明在方法參數(shù)中拨黔,同時提供部分默認值傲武,使用處傳參即可。我復(fù)制過來是19行揪利,原來41行狠持,當(dāng)前文件節(jié)省了21行,不僅如此還減少了層疊情況甜刻,看起來更清晰了≌眨現(xiàn)在完成第一個設(shè)計稿只需要19*7=133行,比原來(42*7=294)優(yōu)化了161行章贞,這種效果還是看得見的
總結(jié):
??本片文章主要介紹了通過方法來抽取公共部分的代碼加以復(fù)用,方便日后的維護拓展蜕径。這里還有個自己輕度封裝簡潔的庫败京,是一個左右widget的package兜喻,同樣可以達到上述效果赡麦,給用戶留了更大的自定義空間帕识,大家有興趣的可以了解使用支持下
上一篇:Flutter入門-02-Dart語言簡講
下一篇:Android開發(fā)之WebView(一)配置&小技巧