[译] 深入了解 Flutter,成功定级腾讯T3-2

组成

Widgets are typically simple, each doing one thing well: Text, Icon, Padding, Center, Column, Row, … To achieve any non-trivial outcome, many widgets must be composed. So our single expression easily becomes a deeply nested tree of widget constructor calls:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

组件除子属性还有其他属性,但是你明白的。

代码编写 UI

编写和编辑深层嵌套的树需要一个优雅的编辑器和一些练习来提高效率。开发人员似乎在布局标记(XML,HTML)中比在代码中更能容忍深度嵌套,但 Flutter 的 UI-as-code 方法确实意味着深层嵌套 code。无论你在组件树中有什么视图逻辑——条件,转换,在读取当前状态时使用的迭代,用于更改它的事件处理程序——也会深深嵌套。

这就是接下来的挑战。


挑战

flutter.io 的 布局教程 提供了一个说明性的例子——看起来像是——一个湖泊探险家应用程序。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是实现此视图的原始组件树:

import ‘package:flutter/material.dart’;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: ‘Flutter Demo’,
home: Scaffold(
appBar: AppBar(title: Text(‘Top Lakes’)),
body: ListView(
children: [
Image.asset(
‘images/lake.jpg’,
width: 600.0,
height: 240.0,
fit: BoxFit.cover,
),
Container(
padding: const EdgeInsets.all(32.0),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
‘Oeschinen Lake Campground’,
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Text(
‘Kandersteg, Switzerland’,
style: TextStyle(color: Colors.grey[500]),
),
],
),
),
Row(
children: [
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: Theme.of(context).primaryColor),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(
‘CALL’,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: Theme.of(context).primaryColor,
),
),
),
],
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.near_me,
color: Theme.of(context).primaryColor),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(
‘ROUTE’,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: Theme.of(context).primaryColor,
),
),
),
],
),
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.share, color: Theme.of(context).primaryColor),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(
‘SHARE’,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: Theme.of(context).primaryColor,
),
),
),
],
),
],
),
),
Container(
padding: const EdgeInsets.all(32.0),
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,
),
),
],
),
),
);
}
}

这只是一个静态组件树,没有实现任何行为。但是将视图逻辑直接嵌入到这样的树中估计不会是一次愉快的体验。

接受挑战。


重新审视代码编写 UI

使用 Flutter 的 UI-as-code 方法时,组件树就是代码。因此,我们可以使用所有常用的代码组织工具来改善这种情况。工具箱中最简单的工具之一就是命名子表达式。这会在语法上将组件树翻出来。而不是

return A(B(C(D(), E())), F());

我们可以命名每个子表达式并得到

final Widget d = D();
final Widget e = E();
final Widget c = C(d, e);
final Widget b = B©;
final Widget f = F();
return A(b, f);

我们的湖泊应用可以重写成下面这样:

import ‘package:flutter/material.dart’;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final Widget imageSection = Image.asset(
‘images/lake.jpg’,
width: 600.0,
height: 240.0,
fit: BoxFit.cover,
);
final Widget titles = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
‘Oeschinen Lake Campground’,
style: TextStyle(fontWeight: FontWeight.bold),
),
),
Text(
‘Kandersteg, Switzerland’,
style: TextStyle(color: Colors.grey[500]),
),
],
);
final Widget stars = Row(
children: [
Icon(Icons.star, color: Colors.red[500]),
Text(‘41’),
],
);
final Widget titleSection = Container(
padding: const EdgeInsets.all(32.0),
child: Row(
children: [
Expanded(child: titles),
stars,
],
),
);
final Widget callAction = Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.call, color: Theme.of(context).primaryColor),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(
‘CALL’,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: Theme.of(context).primaryColor,
),
),
),
],
);
final Widget routeAction = Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.near_me, color: Theme.of(context).primaryColor),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(
‘ROUTE’,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: Theme.of(context).primaryColor,
),
),
),
],
);
final Widget shareAction = Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.share, color: Theme.of(context).primaryColor),
Container(
margin: const EdgeInsets.only(top: 8.0),
child: Text(
‘SHARE’,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: Theme.of(context).primaryColor,
),
),
),
],
);
final Widget actionSection = Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
callAction,
routeAction,
shareAction,
],
),
);
final Widget textSection = Container(
padding: const EdgeInsets.all(32.0),
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,
),
);
final Widget scaffold = Scaffold(
appBar: AppBar(title: Text(‘Top Lakes’)),
body: ListView(
children: [
imageSection,
titleSection,
actionSection,
textSection,
],
),
);
return MaterialApp(
title: ‘Flutter Demo’,
home: scaffold,
);
}
}

缩进级别现在更合理,我们可以通过引入更多名称使子树的缩进级别变得像我们希望的那样浅。更好的是,通过为各个子树提供有意义的名称,我们可以表示每个子树的作用。所以我们现在可以谈谈 xxxAction 子树…并观察到我们在这里面有很多重复的代码!另一个基本的代码组织工具——功能抽象——负责这部分内容:

import ‘package:flutter/material.dart’;

void main() {
runApp(MyApp());
}

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
final Widget imageSection = …
final Widget titles = …
final Widget stars = …
final Widget titleSection = …

Widget action(String label, IconData icon) {
final 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.0),
child: Text(
label,
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}

final Widget actionSection = Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
action(‘CALL’, Icons.call),
action(‘ROUTE’, Icons.near_me),
action(‘SHARE’, Icons.share),
],
),
);
final Widget textSection = …
final Widget scaffold = …
return MaterialApp(
title: ‘Flutter Demo’,
home: scaffold,
);
}
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

小福利:

在当下这个碎片化信息环境的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021大厂最新Android面试真题解析

Android大厂面试真题解析

各个模块学习视频:如数据结构与算法

算法与数据结构资料图

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。
一线互联网架构师

这份体系学习笔记,适应人群:**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!点赞+评论即可获得!

直接点击这里前往我的GitHub中下载,就可以白嫖啦,记得给文章点个赞哦。

结构与算法**

[外链图片转存中…(img-LW4nNqRu-1710881814873)]

只有系统,有方向的学习,才能在段时间内迅速提高自己的技术。
[外链图片转存中…(img-RGqIFJ7l-1710881814873)]

[外链图片转存中…(img-jgmJYilC-1710881814873)]

这份体系学习笔记,适应人群:**第一,**学习知识比较碎片化,没有合理的学习路线与进阶方向。**第二,**开发几年,不知道如何进阶更进一步,比较迷茫。第三,到了合适的年纪,后续不知道该如何发展,转型管理,还是加强技术研究。如果你有需要,我这里恰好有为什么,不来领取!说不定能改变你现在的状态呢!点赞+评论即可获得!

直接点击这里前往我的GitHub中下载,就可以白嫖啦,记得给文章点个赞哦。

  • 25
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值