携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
个人开发环境
1、Flutter 版本:flutter_macos_3.0.5-stable
2、Android Studio :Android Studio Chipmunk | 2021.2.1 Patch 2
3、MacOS Big Sur 11.1
4、Project 使用 Android Studio 的 Flutter 插件初始化
Flutter目录结构简介
当你通过 Android Studio、IntelliJ 或VSCode的Flutter插件创建完项目后,会生成下面的目录结构和文件。
在开始编码之前我们有必要先了解下项目结构文件的各个基本作用(毕竟Flutter的文件目录还是挺少的)
文件夹和文件简述
| 文件夹 | 说明 | 权重 |
|---|---|---|
| android | 用于存放 Android 项目的工程文件,可通过 Android Studio 打开并编译代码 | 重要 |
| ios | 用于存放 iOS 项目的工程文件,可直接通过 Xcode 打开并编译打包 | 重要 |
| lib | 用于存放 Flutter 的项目代码,我们的 Dart 代码基本在这个目录下编写 | 重要 |
| test | 用于存放测试代码,主要用来测试某个功能代码或性能 | 重要 |
| windows | 用于存放桌面端相关的文件 | 普通 |
| build | 编译后生成的相关文件或换缓存 | 普通 |
| 文件 | 说明 |
|---|---|
| flutter_app.iml | 用于配置项目工程文件的路径(一般不需要修改) |
| pubspec.lock | 该文件类似于 Ruby 的Gemfile.lock. 当前项目依赖的 packages 以及对应的版本 |
| analysis_options.yaml | 用于配置分析器,它静态分析 Dart 代码以 检查错误、警告 |
| pubspec.yaml | 用于配置项目的依赖库,它保存当前项目的配置信息 |
| README.md | 用于介绍和说明项目的详细信息 |
好了,现在大概对 FLutter 的项目结构有一个基本的了解,后面随着学习的深入会调整项目的目录文件。
lib 下的 main 文件
创建完项目后 Flutter 会默认在 lib 目录下创建一个 main.dar 文件,里面的代码是一个简单的计数器。
注意,默认计数器示例中的代码,可能随着 Flutter 插件的版本而发生改变。
// main.dart 文件代码
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
效果如图所示
这个实例代码的功能非常简单,只要点击右下角的按钮,中间的数字就会一直累加。
代码分析
1. 导入 package
import 'package:flutter/material.dart';
说明:导入 Material UI 组件库依赖,后续开发基本都会使用到它。
2. 程序入口
void main() => runApp(MyApp());
这里使用了 Dart 语法的简写表达式,如果看不懂的话可能要去复习下 Dart 的语法。
main()函数是程序的执行入口,跟大部分的编程语言一样。
runApp() 需要传输一个 Widget 对象。
MyApp()是我们的要初始化的组件对象。
3. 应用代码
1. 根组件 MaterialApp 类
// 这个 widget 对象将作为你程序的根组件
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
- MyApp 类继承了
StatelessWidget类,而 Flutter 的组件基本都是 widge 类继承的。 - 这里重写了 build 方法,Flutter 构建页面会默认调用 build 方法在,它决定了加载后要展示的UI,后面会大量重写继承了 widge 类的 build 方法。
MaterialApp对象一般定义为根组件,初始化界面。MaterialApp参数home也是传递一个 widget 对象,显示主界面内容,这里使用的是MyHomePage类对象
2. Widget 类
//MyHomePage 类对象代码
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
StatefulWidget类是一个有状态的 widget 组件,它在 widget 的整个生命周期里是可变的,而另一个StatelessWidget类则是无状态的组件类。- 这里重写了
createState方法,并调用_MyHomePageState()类,返回一个State状态类。
3. State 类
class _MyHomePageState extends State<MyHomePage> {
#记录增加数的变量
int _counter = 0;
#一个简单的自增函数
void _incrementCounter() {
setState(() {
_counter++;
});
}
#重写了 build 方法
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
setState()方法的作用是通知 Flutter 框架界面状态发生了变化,然后 Flutter 通过build方法来刷新界面- 界面的实现代码在 build 中编写,
State类重写了 build 方法并返回了一个Scaffold类对象。 Scaffold也是一个 widget,它是一个页面脚手架,方面后面快速构建移动端的界面。body参数为主要的显示内容,传递一个 widget。appBar参数是一个顶部的导航栏,传递一个 widget。floatingActionButton参数代表右下角的按钮,onPressed表示绑定的按钮事件。
整个示例代码的流程为:
- 当按钮被点击后执行 floatingActionButton 绑定的
_incrementCounter方法. _incrementCounter方法自增变量+1 ,同时调用setState通知 Flutter 框架有状态发生变化,需要执行 build 方法刷新界面UI.- 最终显示到界面上.