flutter 零基础入门
by Stanislav Termosa
通过斯坦尼斯拉夫·特莫萨(Stanislav Termosa)
I’ve been hearing about how amazing Flutter is and I’ve decided to try it out to learn something new. I wished to have more topics to discuss with colleagues.
我一直在听说Flutter有多么神奇,我决定尝试一下以学习新的东西。 我希望有更多话题可以与同事讨论。
It started by watching, then reading, and then I started coding. It was a good experience. Apps were running, and everything that was written wasn’t hard to understand.
它从观看然后阅读开始,然后我开始编码。 这是一个很好的经验。 应用程序正在运行,编写的所有内容都不难理解。
However, the process wasn’t smooth enough - some of the details were not explained in that resources. Also, since everything was new to me (the platform itself, programming language, approaches and even mobile app development), the lack of those details was painful.
但是,该过程不够顺利-在该资源中未解释某些细节。 而且,由于所有东西对我来说都是新的(平台本身,编程语言,方法甚至是移动应用程序开发),因此缺少这些细节是很痛苦的。
Any time something didn’t work, I didn’t know what to Google: Dart, Flutter, Window, Screen, Route, Widget?
任何时候,如果某些事情行不通,我都不知道Google会做什么:Dart,Flutter,Window,Screen,Route,Widget?
I decided that reading the documentation on Dart, Flutter and all of its widgets wouldn’t be a good idea as it would be too time consuming. Also, I didn’t have a lot of time as the purpose was to get to know the new thing, and not to become an expert in the field. I thought at that moment that it would be amazing if there was a short guide on Flutter, that would describe all the necessary concepts to understand the framework and be able to write simple apps, but no more!
我认为阅读Dart,Flutter及其所有小部件的文档不是一个好主意,因为这会很耗时。 另外,我没有很多时间,因为目的是要了解新事物,而不是成为该领域的专家。 我当时想,如果有关于Flutter的简短指南会很棒,它会描述所有必要的概念,以理解框架并能够编写简单的应用程序,但仅此而已!
Most of the articles on this topic are well written and straightforward. The problem is that they require you to know some basic things, and those small things are not described in articles that are suppose to give you basic knowledge.
关于该主题的大多数文章都写得很好,也很简单。 问题在于它们要求您了解一些基本知识,而那些小知识并未在旨在为您提供基本知识的文章中进行描述。
In this series, I’ll try to avoid that problem. We’ll start from scratch and create applications sorting out every step we do. During this series, we will use all basic widgets, design a unique interface, interact with native modules, and build our app for both iOS and Android platforms.
在本系列中,我将尝试避免该问题。 我们将从头开始,并创建应用程序,整理出我们执行的每个步骤。 在本系列中,我们将使用所有基本的小部件 ,设计独特的界面 ,与本机模块交互以及为iOS和Android平台构建我们的应用程序。
This series is written from the perspective of a web developer. Most of you are probably familiar with this stack. The analogy with a familiar platform is better than one where you have to build houses or use Animal, Dog, Foo, Bar, etc.
本系列文章是从Web开发人员的角度编写的。 你们中的大多数人可能都熟悉此堆栈。 与您熟悉的平台进行类比比您必须盖房子或使用Animal,Dog,Foo,Bar等的情况更好。
I’ll keep it short, to save your time. For the most curious of you, I’ll put useful links around the text.
为了节省您的时间,我会尽量简短。 对于您中最好奇的人,我将在文本周围放置有用的链接。
Flutter is very new, but a promising platform, that has attracted the attention of large companies who’ve released their apps already. It is interesting because of its simplicity compared to developing web applications, and because of its speed as compared with native applications.
Flutter是一个非常新的平台,但是它是一个很有前途的平台,已经吸引了已经发布应用程序的大公司的关注。 之所以有趣,是因为与开发Web应用程序相比,它比较简单,并且与本机应用程序相比,它具有速度。
High performance and productivity in Flutter are achieved by using several techniques:
Flutter的高性能和高生产率是通过以下几种技术实现的:
Unlike many other popular mobile platforms, Flutter doesn’t use JavaScript in any way. Dart is the programming language. It compiles to binary code, and that’s why it runs with the native performance of Objective-C, Swift, Java or Kotlin.
与许多其他流行的移动平台不同,Flutter 完全不使用JavaScript 。 Dart是编程语言。 它可以编译为二进制代码,这就是为什么它以Objective-C,Swift,Java或Kotlin的本机性能运行的原因。
Flutter doesn’t use native UI components. That may sound awkward at first. However, because components are implemented in Flutter itself, there is no communication layer between the view and your code. Due to this, games hit the best speed for their graphics out of the smartphones. So buttons, text, media elements, background are all drawn by Flutter’s graphics engine. As an aside, it should be mentioned that the bundle of the Flutter “Hello, World” application is quite small: iOS ≈ 2.5Mb and Android ≈ 4Mb.
Flutter 不使用本机UI组件 。 起初听起来很尴尬。 但是,由于组件是在Flutter本身中实现的,因此视图和您的代码之间没有通信层。 因此,游戏在智能手机中以最快的速度获得其图形效果。 因此,按钮,文本,媒体元素,背景都由Flutter的图形引擎绘制。 顺便说一句,应该提到Flutter“ Hello,World”应用程序的捆绑包非常小:iOS≈2.5Mb和Android≈4Mb。
Flutter uses a declarative approach, inspired by the React web framework, to build its UI based on widgets (named “components” in the world of the web). To get more out of widgets, they are rendered only when necessary, usually when their state has been changed (just like the Virtual DOM does for us).
Flutter在React Web框架的启发下使用了一种声明式方法 ,基于小部件(在网络世界中称为“组件”)构建其UI。 为了从小部件中获取更多信息,通常仅在必要时才渲染它们,通常是当它们的状态已更改时(就像Virtual DOM对我们所做的那样)。
In addition to all of the above, the framework has integrated Hot-reload, so typical for the web, but still missing on native platforms. This allows the Flutter framework to automatically rebuild the widget tree, allowing you to quickly view the effects of your changes.
除了上述所有内容之外,该框架还集成了Hot-reload ,这对于Web来说很典型,但在本机平台上仍然缺少。 这使Flutter框架可以自动重建窗口小部件树,从而使您可以快速查看更改的效果。
There is an excellent article on the practical use of these features from an Android developer who recreated his application from Java to Dart and shared his impressions.
一位Android开发人员撰写了一篇有关这些功能的实际使用的出色文章,他从Java将其应用程序重新创建到Dart,并分享了他的印象。
I wanted to share with you some numbers from his article.
我想和你分享他文章中的一些数字。
Java (before): Number of files = 179 and Lines of code 12,176
Java (之前):文件数= 179,代码行12,176
Dart (after): Number of files = 31 and Lines of code 1,735.
Dart (之后):文件数= 31,代码行1,735。
You can read more about the technical details of the platform or look at examples of applications.
您可以阅读有关平台技术细节的更多信息,或查看应用程序示例 。
Dart is a programming language that we’ll use to develop our application in Flutter. Learning it isn’t hard if you have experience with Java or JavaScript. You will quickly get it.
Dart是一种编程语言,我们将使用它在Flutter中开发应用程序。 如果您有Java或JavaScript的经验,学习并不难。 您会很快得到它。
I tried to write an article on Dart for you, to describe the minimal scope that is required for Flutter. After several attempts, I was still failing to write it so that it was short and covered the core concepts at the same time. Authors of A Tour of the Dart Language coped well with this task!
我试图为您写一篇有关Dart的文章,以描述Flutter所需的最小范围。 经过几次尝试,我仍然未能编写它,以使其简短并同时涵盖了核心概念。 “Dart语言之旅”的作者很好地完成了这一任务!
This topic, just like a Dart, is well covered in the official guide — so I won’t copy it here.
就像Dart一样,该主题在官方指南中也有介绍,因此在此不再赘述。
Go through this short setup guide, by choosing your OS and following it step-by-step. Also, configure your preferred editor to work with Dart and Flutter (usually it requires 2 different plugins). Run your application to make sure that you are ready to continue.
选择您的操作系统并逐步进行操作,以通读此简短的设置指南 。 另外, 将您喜欢的编辑器配置为与Dart和Flutter配合使用(通常需要2个不同的插件)。 运行您的应用程序 ,以确保您准备好继续。
Here is a tip for MacOS users. If you don’t like how much space is wasted by virtual device bezels, you can turn them off, and switch to an iPhone 8 model (it is not as long as iPhone X):
这是MacOS用户的提示。 如果您不喜欢虚拟设备挡板浪费了多少空间,则可以将其关闭,然后切换到iPhone 8型号(它不像iPhone X那样长):
It is possible to live without virtual buttons as we have hot keys: Shift + Cmd (⌘) + H - go home, Cmd (⌘) + Right - rotate the phone, and you can find more in the Hardware menu. I would also recommend to turn on the on-screen keyboard, as it is important to understand if your application is usable when half of the screen is overlapped. To do so you press Cmd (⌘) + K after you focus on an input field.
由于我们具有热键,因此可以不使用虚拟按钮来生活: Shift + Cmd (⌘) + H-回家, Cmd( ⌘) +右键-旋转手机,您可以在Hardware菜单中找到更多功能。 我还建议打开屏幕键盘,因为了解一半的屏幕重叠时您的应用程序是否可用非常重要。 为此,请在关注输入字段后按Cmd( md )+K 。
Let’s first see what’s in the project generated by the Flutter framework:
我们首先来看一下Flutter框架生成的项目中的内容:
lib/ - just as pub (Dart’s package manager), all the code will be here
lib / -和pub (Dart的包管理器)一样,所有代码都在这里
pubspec.yml - stores a list of packages that are required to run the application, just like package.json does it. You should remember that in Flutter projects you cannot use pub directly, but instead, you will use the Flutter command: flutter pub get <package_na
me>
pubspec.yml-存储运行该应用程序所需的软件包列表,就像package.json一样。 您应该记住,在Flutter项目中您不能直接使用pub,而是使用Flutter命令: flutter pub get <package_na
me>
test/ - I’m sure you know what this is about. Right? You can run them via flutter test
测试/ -我确定您知道这是什么。 对? 您可以通过抖动测试来运行它们
ios/ & android/ - the code specific for each platform, including app icons and settings where you set what permissions you’ll need for your application (like access to location, Bluetooth).
ios / & android / -每种平台专用的代码,包括应用程序图标和设置,您可以在其中设置应用程序所需的权限(例如访问位置,蓝牙)。
We don’t need to know more about the files in the folder for now. Let’s open the lib/ folder where main.dart is waiting for us. As you can guess this one is the entry point of our application. Just like in the C language (or tons of others) the app will be executed by calling the main() function.
现在我们不需要了解更多关于文件夹中文件的信息。 让我们打开main.dart等待我们的lib /文件夹。 您可以猜到这是我们应用程序的切入点。 就像使用C语言(或其他大量语言)一样,该应用将通过调用main()函数来执行。
In Flutter everything is built on Widgets. UI elements, styles, themes, and even state is managed in specific Widgets. Let’s start from a small application.
在Flutter中,所有内容都基于Widget。 UI元素,样式,主题甚至状态在特定的小部件中进行管理。 让我们从一个小应用程序开始。
Replace the code from main.dart with the one given below, read the comments, and run the application.
用下面给出的代码替换main.dart中的代码,阅读注释,然后运行该应用程序。
runApp(…) only has a widget argument. The widget will become the root widget for the whole application. BTW, changing the root widget cannot be handled by Hot-reload so you’ll have to restart your application to see changes.
runApp(…)仅具有一个小部件参数。 该小部件将成为整个应用程序的根小部件。 顺便说一句,更改根窗口小部件无法通过热重载来处理,因此您必须重新启动应用程序才能查看更改。
Text(…) - Flutter cannot render text without knowing what’s the preference for text direction. To render text, we have to set Text.textDirection. Don’t confuse it with the CSS text-align rule. It is the analogy of direction - the part of the internationalization API. However, don’t worry, we won’t need to set it for each Text widget - later we’ll see how to set it for the whole app.
文本(…) -Flutter无法在不知道文本方向偏好的情况下渲染文本。 要渲染文本,我们必须设置Text.textDirection 。 请勿将其与CSS 文本对齐规则混淆。 这是方向的类比-国际化API的一部分。 但是,请放心,我们不需要为每个Text小部件设置它-稍后我们将了解如何为整个应用程序设置它。
Is your application running already? Yay! “Hello, World!” is on the screen now. Right? Eh, something went wrong.
您的应用程序已经在运行吗? 好极了! “你好,世界!” 现在在屏幕上。 对? 嗯,出了点问题。
The text is overlapped by the notch. We can use the whole screen for our application, and we have printed our content at the very top of it where system information is also rendered.
文字被切口覆盖。 我们可以将整个屏幕用于我们的应用程序,并且我们已经在内容的最顶部打印了我们的内容,还显示了系统信息。
Let’s try to shift our content.
让我们尝试改变我们的内容。
Center(…) is the widget that aligns another widget given in child property in the center of itself. You’ll often see child and children properties in Flutter applications, because almost all widgets are using them if they need one or several widgets to be rendered inside of them.
Center(…)是用于将子属性中给定的另一个窗口小部件对准其中心的窗口小部件。 您会经常在Flutter应用程序中看到child和children属性,因为如果需要在其内部呈现一个或几个小部件,几乎所有小部件都在使用它们。
A composition of widgets in Flutter is used to represent an interface, to change its look, and to share data. For example, Directionality(…) sets the direction for the text for all nested widgets (so we don’t need to specify it for Text every time).
Flutter中的小部件组合用于表示界面,更改其外观并共享数据。 例如, Directionality(...)为所有嵌套的小部件设置文本的方向(因此我们不必每次都为Text指定它的方向)。
Let’s take a look at one very important widget, and change the design of our application:
让我们看一个非常重要的小部件,并更改应用程序的设计:
There are several options on how to use the Color(…) widget. We have used the widget with the number given to it using hexadecimal notation. This looks almost the same as we set HEX-colors on the web, but here we have 2 additional symbols at the beginning. This is a number that represents the transparency where 0x00 is fully transparent, and 0xFF is not transparent at all.
关于如何使用Color(…)小部件,有几个选项。 我们已经使用了小部件,并使用十六进制表示法为其指定了编号。 这看起来与我们在网络上设置十六进制颜色几乎相同,但是在此处开头有两个其他符号。 这是代表透明度的数字,其中0x00是完全透明的,而0xFF根本不是透明的。
TextStyle(…) is more interesting. You can use it to set a color, font size and weight, line spacing, underline text, etc.
TextStyle(…)更有趣。 您可以使用它来设置颜色,字体大小和粗细,行距,下划线文本等。
The Flutter application is complete! You can read how to build it for Android and iOS, where you can also learn how to publish it to the relevant app store. If it’s not enough for you, I’ve covered a few more topics below.
Flutter应用程序已完成! 您可以阅读如何在Android和iOS上构建它,还可以在其中了解如何将其发布到相关的应用商店。 如果您还不够,那么我在下面介绍了更多主题。
Now we know how easy it is to use widgets. The next logical step would be to create our widgets. I’ve mentioned before that there are two kinds of widgets (actually more, but let’s not over complicate it for now). There are stateless and stateful widgets.
现在我们知道使用小部件很容易。 下一个合乎逻辑的步骤是创建我们的小部件。 我之前已经提到过,有两种小部件(实际上更多,但现在让我们不要过于复杂)。 有无状态和有状态的小部件。
We’ve been using stateless widgets in the previous examples. “Stateless” doesn’t mean they don’t have a state at all. Widgets are Dart classes, that can be declared with properties. But changing those properties in a stateless widget won’t affect what has already been rendered. Updating properties of a stateful widget will trigger life cycle hooks and render its content using the new state. We’ll start with Stateless widgets as they seem to be a bit easier.
在前面的示例中,我们一直在使用无状态小部件。 “无状态”并不意味着他们根本没有状态。 小部件是Dart类,可以使用属性声明。 但是,在无状态小部件中更改这些属性不会影响已经呈现的内容。 更新有状态窗口小部件的属性将触发生命周期挂钩,并使用新状态来呈现其内容。 我们将从无状态小部件开始,因为它们似乎要容易一些。
To create one, we need:
要创建一个,我们需要:
To extend our class from StatelessWidget.
从StatelessWidget扩展我们的课程。
Implement the build() method, that will receive one argument of type BuildContext and return a result of type Widget.
实现build()方法,该方法将接收一个BuildContext类型的参数并返回Widget类型的结果。
An example of the widget with an argument:
带有参数的小部件的示例:
I have nothing more to add about Stateless widgets. They are simple.
我无话可说了。 他们很简单。
Notice that once we have moved our application content to the separate widget, the application is re-rendered each time we save our changes. This is hot-reload in action.
请注意,一旦我们将应用程序内容移至单独的小部件,则每次保存更改时都会重新渲染该应用程序。 这是热重装。
It is also crucial to understand, that while you are working in development mode with hot-reload enabled, the application will work much slower than in release mode.
同样重要的是要理解,当您在启用了热重载的开发模式下工作时,该应用程序的运行速度将比发行版下慢得多。
We will create a StatefulWidget in the next section. To make sure it will be interesting we need to be able to change the state of the widget, right? We’ll use GestureDetector(…) for this purpose. This widget will not render anything to the screen but handles user interaction with the screen and calls related functions given to it.
我们将在下一部分中创建一个StatefulWidget。 为了确保有趣,我们需要能够更改小部件的状态,对吗? 为此,我们将使用GestureDetector(…) 。 该小部件不会在屏幕上呈现任何内容,但会处理用户与屏幕的交互并调用赋予它的相关功能。
The example below creates a blue button in the center of the screen, and once this button is pressed, the text is printed to the terminal:
下面的示例在屏幕中央创建一个蓝色按钮,一旦按下该按钮,文本将被打印到终端:
Press the button, and the message will be printed to the terminal. Press it again, and the text will appear again.
按下按钮,消息将被打印到终端上。 再按一次,该文本将再次出现。
StatefulWidget’s are simple. Yeah, even simpler than StatelessWidget’s! However, there is a nuance. They do not exist by themselves. They require an extra class to store the state of the widget. Moreover, the visual part of the widget becomes its state.
StatefulWidget很简单。 是的,甚至比StatelessWidget更简单! 但是,有细微差别。 它们本身并不存在。 他们需要一个额外的类来存储小部件的状态。 而且,小部件的可视部分变为其状态。
Here is the example of the StatefulWidget class:
这是StatefulWidget类的示例:
We’ve created an “empty” widget that implements only one method and doesn’t contain state or UI representation. Forcing such separation, Flutter seeks greater optimization of the application.
我们创建了一个“空”小部件,该小部件仅实现一种方法,并且不包含状态或UI表示形式。 强制进行这种分离,Flutter寻求对应用程序的更大优化。
The state object is also not complicated. Indeed, it is just like our StatelessWidget. The main difference is its parent class.
状态对象也不复杂。 确实,这就像我们的StatelessWidget一样 。 主要区别在于其父类。
I named our state class starting with an underscore. In the Dart language all names that begin with an underscore are private (unlike JavaScript or Python they are truly unavailable outside of the library). Usually, we don’t need to expose our state classes outside of the library, so it is good practice to keep them private.
我以下划线开头来命名我们的状态类。 在Dart语言中,所有以下划线开头的名称都是私有的(与JavaScript或Python不同,它们在库外部确实不可用)。 通常,我们不需要在库外部公开状态类,因此,最好将它们保持私有状态。
We’ve built such a wonderful application. Great result!
我们已经构建了一个很棒的应用程序。 好结果!
Before we end this part, let’s take a look at a few more interesting widgets. This time we’ll write more code at once, and I won’t explain every line. You can probably already understand most of the code:
在结束本部分之前,让我们看一些其他有趣的小部件。 这次我们将一次编写更多代码,而我不会解释每一行。 您可能已经了解了大多数代码:
So we have used two new widgets: Column() and Row(). It is not difficult to guess what their purpose is.
因此,我们使用了两个新的小部件: Column()和Row() 。 不难猜测它们的目的是什么。
In the next article, we will look at them more precisely. We will also learn how to assemble several widgets and create a sexy app using Flutter’s Material library.
在下一篇文章中,我们将更精确地研究它们。 我们还将学习如何使用Flutter的Material库组装几个小部件并创建一个性感的应用程序。
If you wish to learn more about mentioned topics here is the list of interesting links:
如果您想了解有关提到的主题的更多信息,请参见以下有趣的链接列表:
Coding using VS Code and IntelliJ
使用VS Code和IntelliJ进行编码
It is also important to read about Hot reload to understand when and why your application may not be updated automatically.
阅读有关热重装的信息也很重要,以了解何时以及为什么您的应用程序可能不会自动更新。
翻译自: https://www.freecodecamp.org/news/an-introduction-to-flutter-the-basics-9fe541fd39e2/
flutter 零基础入门