void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget 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
方法的小部件,它很难阅读、理解和维护。
现在让我们看看我将如何重写它:
import ‘package:flutter/material.dart’;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘Flutter layout demo’,
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({
Key key,
}) : super(key: key);
@override
Widget 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);
@override
Widget 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);
@override
Widget 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);
@override
Widget 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);
@override
Widget build(BuildContext context) {
return Text(
‘Kandersteg, Switzerland’,
style: TextStyle(
color: Colors.grey[500],
),
);
}
}
class _Likes extends StatelessWidget {
const _Likes({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Row(
children: [
Icon(
Icons.star,
color: Colors.red[500],
),
Text(‘41’),
],
);
}
}
class _Buttons extends StatelessWidget {
const _Buttons({
Key key,
}) : super(key: key);
@override
Widget 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;
@override
Widget 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);
@override
Widget 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,
),
);
}
}
你不觉得这更易读吗?
====================================================================
我理解为什么教程不经常这样做:它需要更多行(在我的示例中为 100 行),人们可能想知道为什么我们要创建这么多其他小部件。由于教程旨在专注于一个概念,因此这样编写它们可能会适得其反。但结果是,新采用者可能倾向于在他们的build
方法中放置一个大的小部件树。
让我们看看为布局的每个部分都有一个独特的小部件有什么好处:
我们为布局的每个语义部分创建一个小部件。因此,每个小部件都有一个较小的build
方法。它更易于阅读,因为您无需滚动即可到达小部件的末尾。
每个小部件都有一个与其角色匹配的名称,这称为语义命名。通过这样做,当我们阅读代码时,更容易在我们的脑海中映射代码的哪一部分与我们在应用程序上看到的内容相匹配。我在这里看到了可理解性方面的两个改进:
\1. 当我们阅读其他地方引用的此类小部件时,我们几乎知道它的作用,而无需查看其实现。
2.在阅读带有语义命名的小部件的构建方法之前,我们已经对其内容有一个大致的了解。
如果您必须更换一个组件或更改一个部件,它只会在一个地方,与其他小部件的其余部分分开。多亏了这种做法,它更不容易出错,因为每个小部件的角色都得到了很好的定义。在您的应用程序甚至另一个应用程序中的另一个页面中共享布局的一部分也将更加容易。
前面的所有原因应该足以让您采用这种方式来创建 Flutter 应用程序,但是这样做还有一个好处:我们提高了应用程序的性能,因为每个小部件都可以与其他小部件分开重建(事实并非如此如果我们使用方法来分隔我们的布局部分)。例如,假设我们必须在单击它时增加红星旁边的数字。在这个版本中,我们可以制作_Likes
一个StatefulWidget
并处理这里的增量。当用户点击星星时,只有_Likes
小部件会被重建。在第一个版本中,MyApp
如果我们将其设为StatefulWidget
.
Flutter 文档中也解释了这种最佳实践:
当
setState()
在状态上调用时,所有后代小部件都将重建。因此,将setState()
调用本地化到 UI 实际需要更改的子树部分。如果更改包含在树的一小部分,请避免在树的高处调用 setState()。
另一个优点是能够const
更频繁地使用关键字。然后可以缓存和重新使用小部件。正如Flutter 文档所述:
重用小部件比创建新的(但配置相同的)小部件要高效得多。
=======================================================================
如您所见,通过为布局的每个语义部分创建一个小部件,我们编写了更多代码。我们可以在 Visual Studio Code 中使用Dart扩展提供的stless
和stful
片段,
为了我自己的需要,我创建了新的片段,称为sless
和sful
,这样我的工作效率比以往任何时候都高。如果您希望在 Visual Studio Code 中使用它们,则必须遵循此文档并添加以下内容:
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
用Dart扩展提供的stless
和stful
片段,
为了我自己的需要,我创建了新的片段,称为sless
和sful
,这样我的工作效率比以往任何时候都高。如果您希望在 Visual Studio Code 中使用它们,则必须遵循此文档并添加以下内容:
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-BHTpsA8z-1715528752610)]
[外链图片转存中…(img-0zQsTJdp-1715528752611)]
[外链图片转存中…(img-UZj6Y0Ti-1715528752612)]
[外链图片转存中…(img-Dt6pOBTj-1715528752613)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!