日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Flutter一切皆widget但是不要将所有东西放入一个widget

發(fā)布時間:2025/3/19 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Flutter一切皆widget但是不要将所有东西放入一个widget 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本文主要介紹Flutter一切皆widget但是不要將所有東西放入一個widget

作為 Flutter 開發(fā)人員,我相信您在您的開發(fā)生活中至少聽說過這句流行的句子:“**一切都是widget”。這是 Flutter 的口頭禪,它揭示了這個非常好的 SDK 的內(nèi)在力量!

當(dāng)我們在widgets目錄中,我們可以看到很多小部件,如Padding,Align,SizedBox,等。我們通過組合它們來創(chuàng)建其他小部件,我發(fā)現(xiàn)這種方法可擴展、強大且易于理解。

但是當(dāng)我閱讀 一些我在互聯(lián)網(wǎng)上找到的或由新采用者編寫的源代碼時,有一件讓我震驚的事情:擁有大量build**`**方法的趨勢,實例化很多小部件!我發(fā)現(xiàn)這很難閱讀、理解和維護。

作為軟件開發(fā)人員,我們必須記住,軟件的真實生活從第一次發(fā)布給用戶開始。該軟件的源代碼將由其他人(包括您未來的您)閱讀和維護,這就是為什么保持我們的代碼簡單、易于閱讀和理解非常重要。

“小部件中的一切”的示例可以在Flutter 文檔本身中找到。本教程的目標(biāo)是展示如何構(gòu)建此布局:

最終代碼達到了它的目的:展示如何簡單地創(chuàng)建上述布局。正如我們所見,甚至還有一些變量和方法可以為布局的各個部分提供語義。這是一個很好的觀點,因為它使代碼更容易理解。

import 'package:flutter/material.dart';void main() {runApp(MyApp()); }class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {Widget titleSection = Container(padding: const EdgeInsets.all(32),child: Row(children: [Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Container(padding: const EdgeInsets.only(bottom: 8),child: Text('Oeschinen Lake Campground',style: TextStyle(fontWeight: FontWeight.bold,),),),Text('Kandersteg, Switzerland',style: TextStyle(color: Colors.grey[500],),),],),),Icon(Icons.star,color: Colors.red[500],),Text('41'),],),);Color color = Theme.of(context).primaryColor;Widget buttonSection = Container(child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [_buildButtonColumn(color, Icons.call, 'CALL'),_buildButtonColumn(color, Icons.near_me, 'ROUTE'),_buildButtonColumn(color, Icons.share, 'SHARE'),],),);Widget textSection = Container(padding: const EdgeInsets.all(32),child: Text('Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese ''Alps. Situated 1,578 meters above sea level, it is one of the ''larger Alpine Lakes. A gondola ride from Kandersteg, followed by a ''half-hour walk through pastures and pine forest, leads you to the ''lake, which warms to 20 degrees Celsius in the summer. Activities ''enjoyed here include rowing, and riding the summer toboggan run.',softWrap: true,),);return MaterialApp(title: 'Flutter layout demo',home: Scaffold(appBar: AppBar(title: Text('Flutter layout demo'),),body: ListView(children: [Image.asset('images/lake.jpg',width: 600,height: 240,fit: BoxFit.cover,),titleSection,buttonSection,textSection,],),),);}Column _buildButtonColumn(Color color, IconData icon, String label) {return Column(mainAxisSize: MainAxisSize.min,mainAxisAlignment: MainAxisAlignment.center,children: [Icon(icon, color: color),Container(margin: const EdgeInsets.only(top: 8),child: Text(label,style: TextStyle(fontSize: 12,fontWeight: FontWeight.w400,color: color,),),),],);} }

事實上,情況可能更糟。這是我不喜歡的這段代碼的典型多合一小部件版本:。

import 'package:flutter/material.dart';void main() {runApp(MyApp()); }class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {Color color = Theme.of(context).primaryColor;return MaterialApp(title: 'Flutter layout demo',home: Scaffold(appBar: AppBar(title: Text('Flutter layout demo'),),body: ListView(children: [Image.asset('images/lake.jpg',width: 600,height: 240,fit: BoxFit.cover,),Container(padding: const EdgeInsets.all(32),child: Row(children: [Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [Container(padding: const EdgeInsets.only(bottom: 8),child: Text('Oeschinen Lake Campground',style: TextStyle(fontWeight: FontWeight.bold,),),),Text('Kandersteg, Switzerland',style: TextStyle(color: Colors.grey[500],),),],),),Icon(Icons.star,color: Colors.red[500],),Text('41'),],),),Container(child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [Column(mainAxisSize: MainAxisSize.min,mainAxisAlignment: MainAxisAlignment.center,children: [Icon(Icons.call, color: color),Container(margin: const EdgeInsets.only(top: 8),child: Text('CALL',style: TextStyle(fontSize: 12,fontWeight: FontWeight.w400,color: color,),),),],),Column(mainAxisSize: MainAxisSize.min,mainAxisAlignment: MainAxisAlignment.center,children: [Icon(Icons.near_me, color: color),Container(margin: const EdgeInsets.only(top: 8),child: Text('ROUTE',style: TextStyle(fontSize: 12,fontWeight: FontWeight.w400,color: color,),),),],),Column(mainAxisSize: MainAxisSize.min,mainAxisAlignment: MainAxisAlignment.center,children: [Icon(Icons.share, color: color),Container(margin: const EdgeInsets.only(top: 8),child: Text('SHARE',style: TextStyle(fontSize: 12,fontWeight: FontWeight.w400,color: color,),),),],),],),),Container(padding: const EdgeInsets.all(32),child: Text('Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese ''Alps. Situated 1,578 meters above sea level, it is one of the ''larger Alpine Lakes. A gondola ride from Kandersteg, followed by a ''half-hour walk through pastures and pine forest, leads you to the ''lake, which warms to 20 degrees Celsius in the summer. Activities ''enjoyed here include rowing, and riding the summer toboggan run.',softWrap: true,),),],),),);} }

在第二個版本中,我們有一個大build方法的小部件,它很難閱讀、理解和維護。

現(xiàn)在讓我們看看我將如何重寫它:

import 'package:flutter/material.dart';void main() {runApp(MyApp()); }class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter layout demo',home: const HomePage(),);} }class HomePage extends StatelessWidget {const HomePage({Key key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text('Flutter layout demo'),),body: ListView(children: [const _Header(),const _SubHeader(),const _Buttons(),const _Description(),],),);} }class _Header extends StatelessWidget {const _Header({Key key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Image.asset('images/lake.jpg',width: 600,height: 240,fit: BoxFit.cover,);} }class _SubHeader extends StatelessWidget {const _SubHeader({Key key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Container(padding: const EdgeInsets.all(32),child: Row(children: [Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start,children: [const _Title(),const _SubTitle(),],),),const _Likes(),],),);} }class _Title extends StatelessWidget {const _Title({Key key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Container(padding: const EdgeInsets.only(bottom: 8),child: Text('Oeschinen Lake Campground',style: TextStyle(fontWeight: FontWeight.bold,),),);} }class _SubTitle extends StatelessWidget {const _SubTitle({Key key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Text('Kandersteg, Switzerland',style: TextStyle(color: Colors.grey[500],),);} }class _Likes extends StatelessWidget {const _Likes({Key key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Row(children: <Widget>[Icon(Icons.star,color: Colors.red[500],),Text('41'),],);} }class _Buttons extends StatelessWidget {const _Buttons({Key key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Container(child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [const _Button(icon: Icons.call, text: 'CALL'),const _Button(icon: Icons.share, text: 'ROUTE'),const _Button(icon: Icons.share, text: 'SHARE'),],),);} }class _Button extends StatelessWidget {const _Button({Key key,@required this.icon,@required this.text,}) : assert(icon != null),assert(text != null),super(key: key);final IconData icon;final String text;@overrideWidget build(BuildContext context) {Color color = Theme.of(context).primaryColor;return Column(mainAxisSize: MainAxisSize.min,mainAxisAlignment: MainAxisAlignment.center,children: [Icon(icon, color: color),Container(margin: const EdgeInsets.only(top: 8),child: Text(text,style: TextStyle(fontSize: 12,fontWeight: FontWeight.w400,color: color,),),),],);} }class _Description extends StatelessWidget {const _Description({Key key,}) : super(key: key);@overrideWidget build(BuildContext context) {return Container(padding: const EdgeInsets.all(32),child: Text('Lake Oeschinen lies at the foot of the Blüemlisalp in the Bernese ''Alps. Situated 1,578 meters above sea level, it is one of the ''larger Alpine Lakes. A gondola ride from Kandersteg, followed by a ''half-hour walk through pastures and pine forest, leads you to the ''lake, which warms to 20 degrees Celsius in the summer. Activities ''enjoyed here include rowing, and riding the summer toboggan run.',softWrap: true,),);} }

你不覺得這更易讀嗎?

🤔 有什么好處?

我理解為什么教程不經(jīng)常這樣做:它需要更多行(在我的示例中為 100 行),人們可能想知道為什么我們要創(chuàng)建這么多其他小部件。由于教程旨在專注于一個概念,因此這樣編寫它們可能會適得其反。但結(jié)果是,新采用者可能傾向于在他們的build方法中放置一個大的小部件樹。
讓我們看看為布局的每個部分都有一個獨特的小部件有什么好處:

可讀性

我們?yōu)椴季值拿總€語義部分創(chuàng)建一個小部件。因此,每個小部件都有一個較小的build方法。它更易于閱讀,因為您無需滾動即可到達小部件的末尾。

可理解性

每個小部件都有一個與其角色匹配的名稱,這稱為語義命名。通過這樣做,當(dāng)我們閱讀代碼時,更容易在我們的腦海中映射代碼的哪一部分與我們在應(yīng)用程序上看到的內(nèi)容相匹配。我在這里看到了可理解性方面的兩個改進:
\1. 當(dāng)我們閱讀其他地方引用的此類小部件時,我們幾乎知道它的作用,而無需查看其實現(xiàn)。
2.在閱讀帶有語義命名的小部件的構(gòu)建方法之前,我們已經(jīng)對其內(nèi)容有一個大致的了解。

可維護性

如果您必須更換一個組件或更改一個部件,它只會在一個地方,與其他小部件的其余部分分開。多虧了這種做法,它更不容易出錯,因為每個小部件的角色都得到了很好的定義。在您的應(yīng)用程序甚至另一個應(yīng)用程序中的另一個頁面中共享布局的一部分也將更加容易。

Performances

前面的所有原因應(yīng)該足以讓您采用這種方式來創(chuàng)建 Flutter 應(yīng)用程序,但是這樣做還有一個好處:我們提高了應(yīng)用程序的性能,因為每個小部件都可以與其他小部件分開重建(事實并非如此如果我們使用方法來分隔我們的布局部分)。例如,假設(shè)我們必須在單擊它時增加紅星旁邊的數(shù)字。在這個版本中,我們可以制作_Likes一個StatefulWidget并處理這里的增量。當(dāng)用戶點擊星星時,只有_Likes小部件會被重建。在第一個版本中,MyApp如果我們將其設(shè)為StatefulWidget.

Flutter 文檔中也解釋了這種最佳實踐:

當(dāng)setState()在狀態(tài)上調(diào)用時,所有后代小部件都將重建。因此,將setState()調(diào)用本地化到 UI 實際需要更改的子樹部分。如果更改包含在樹的一小部分,請避免在樹的高處調(diào)用 setState()。

另一個優(yōu)點是能夠const更頻繁地使用關(guān)鍵字。然后可以緩存和重新使用小部件。正如Flutter 文檔所述:

重用小部件比創(chuàng)建新的(但配置相同的)小部件要高效得多。

?? 如何提高工作效率?

如您所見,通過為布局的每個語義部分創(chuàng)建一個小部件,我們編寫了更多代碼。我們可以在 Visual Studio Code 中使用Dart擴展提供的stless和stful片段,

為了我自己的需要,我創(chuàng)建了新的片段,稱為sless和sful,這樣我的工作效率比以往任何時候都高。如果您希望在 Visual Studio Code 中使用它們,則必須遵循此文檔并添加以下內(nèi)容:

{"Flutter stateless widget": {"scope": "dart","prefix": "sless","description": "Insert a StatelessWidget","body": ["class $1 extends StatelessWidget {"," const $1({"," Key key,"," }) : super(key: key);",""," @override"," Widget build(BuildContext context) {"," return Container("," $2"," );"," }","}"]},"Flutter stateful widget": {"scope": "dart","prefix": "sful","description": "Insert a StatefulWidget","body": ["class $1 extends StatefulWidget {"," const $1({"," Key key,"," }) : super(key: key);",""," @override"," _$1State createState() => _$1State();","}","","class _$1State extends State<$1> {"," @override"," Widget build(BuildContext context) {"," return Container("," $2"," );"," }","}"]}, }

📕 結(jié)論

我相信這是編寫 Flutter 應(yīng)用程序的好方法,我希望你也相信。如果不是這樣,我對你的意見很感興趣😉!

從現(xiàn)在開始,記住這句話:“Everything’s a widget but don’t put everything in one widget!”。

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的Flutter一切皆widget但是不要将所有东西放入一个widget的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。