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.在阅读带有语义命名的小部件的构建方法之前,我们已经对其内容有一个大致的了解。

可维护性


如果您必须更换一个组件或更改一个部件,它只会在一个地方,与其他小部件的其余部分分开。多亏了这种做法,它更不容易出错,因为每个小部件的角色都得到了很好的定义。在您的应用程序甚至另一个应用程序中的另一个页面中共享布局的一部分也将更加容易。

Performances


前面的所有原因应该足以让您采用这种方式来创建 Flutter 应用程序,但是这样做还有一个好处:我们提高了应用程序的性能,因为每个小部件都可以与其他小部件分开重建(事实并非如此如果我们使用方法来分隔我们的布局部分)。例如,假设我们必须在单击它时增加红星旁边的数字。在这个版本中,我们可以制作_Likes一个StatefulWidget并处理这里的增量。当用户点击星星时,只有_Likes小部件会被重建。在第一个版本中,MyApp如果我们将其设为StatefulWidget.

Flutter 文档中也解释了这种最佳实践:

setState()在状态上调用时,所有后代小部件都将重建。因此,将setState()调用本地化到 UI 实际需要更改的子树部分。如果更改包含在树的一小部分,请避免在树的高处调用 setState()。

另一个优点是能够const更频繁地使用关键字。然后可以缓存和重新使用小部件。正如Flutter 文档所述:

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

⚡️ 如何提高工作效率?

=======================================================================

如您所见,通过为布局的每个语义部分创建一个小部件,我们编写了更多代码。我们可以在 Visual Studio Code 中使用Dart扩展提供的stlessstful片段,

为了我自己的需要,我创建了新的片段,称为slesssful,这样我的工作效率比以往任何时候都高。如果您希望在 Visual Studio Code 中使用它们,则必须遵循此文档并添加以下内容:

文末

初级工程师拿到需求会直接开始做,然后做着做着发现有问题了,要么技术实现不了,要么逻辑有问题。

而高级工程师拿到需求会考虑很多,技术的可行性?对现有业务有没有帮助?对现有技术架构的影响?扩展性如何?等等…之后才会再进行设计编码阶段。

而现在随着跨平台开发,混合式开发,前端开发之类的热门,Android开发者需要学习和掌握的技术也在不断的增加。

通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。

混合式开发,微信小程序。都是得学会并且熟练的

这些是Android相关技术的内核,还有Java进阶

高级进阶必备的一些技术。像移动开发架构项目实战等

Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系

以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。

而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?

就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?

我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。

喜欢的话请帮忙转发点赞一下能让更多有需要的人看到吧。谢谢!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
增加。

通过和一些行业里的朋友交流讨论,以及参考现在大厂面试的要求。我们花了差不多一个月时间整理出了这份Android高级工程师需要掌握的所有知识体系。你可以看下掌握了多少。

混合式开发,微信小程序。都是得学会并且熟练的

[外链图片转存中…(img-unRiSqmF-1714963483156)]

这些是Android相关技术的内核,还有Java进阶

[外链图片转存中…(img-4wPov41S-1714963483158)]

高级进阶必备的一些技术。像移动开发架构项目实战等

[外链图片转存中…(img-A1oMs2fH-1714963483158)]

Android前沿技术;包括了组件化,热升级和热修复,以及各种架构跟框架的详细技术体系

[外链图片转存中…(img-h6C83GYa-1714963483159)]

以上即是我们整理的Android高级工程师需要掌握的技术体系了。可能很多朋友觉得很多技术自己都会了,只是一些新的技术不清楚而已。应该没什么太大的问题。

而这恰恰是问题所在!为什么别人高级工程师能年限突破30万,而你只有十几万呢?

就因为你只需补充你自己认为需要的,但并不知道企业需要的。这个就特别容易造成差距。因为你的技术体系并不系统,是零碎的,散乱的。那么你凭什么突破30万年薪呢?

我这些话比较直接,可能会戳到一些人的玻璃心,但是我知道肯定会对一些人起到点醒的效果的。而但凡只要有人因为我的这份高级系统大纲以及这些话找到了方向,并且付出行动去提升自我,为了成功变得更加努力。那么我做的这些就都有了意义。

喜欢的话请帮忙转发点赞一下能让更多有需要的人看到吧。谢谢!

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐