Flutter 语法入门

下面从 Flutter 开发会用到的 Dart 语法 开始讲。Dart 是一门强类型、面向对象、支持空安全和异步编程的语言。Flutter 的页面、组件、状态、网络请求、路由逻辑,基本都写在 Dart 里。

  1. Dart 程序入口
    Dart 程序从 main() 函数开始。

void main() {
print('Hello Dart');
}
Flutter 项目里也是这样:

void main() {
runApp(const MyApp());
}
解释:

void
表示函数没有返回值。

main()
是程序入口函数。

print()
用于控制台输出。

  1. 注释
    单行注释:

// 这是单行注释
多行注释:

/*
这是多行注释
*/
文档注释:

/// 用户模型
class User {}

  1. 变量声明
    Dart 常见变量声明方式有:

var name = 'Tom';
String title = '首页';
int age = 18;
double price = 99.5;
bool isLogin = true;
3.1 var
var 会自动推断类型。

var name = 'Tom';
等价于:

String name = 'Tom';
但类型确定后不能变:

var name = 'Tom';

name = 'Jerry'; // 可以
name = 123; // 错误,name 已经是 String
3.2 明确类型
String name = 'Tom';
int age = 18;
double score = 98.5;
bool passed = true;
这种写法更清晰,业务模型里常用。

  1. final 和 const
    4.1 final
    final 表示变量只能赋值一次。

final name = 'Tom';
name = 'Jerry'; // 错误
可以运行时赋值:

final now = DateTime.now();
因为 DateTime.now() 是运行时才知道的。

4.2 const
const 表示编译期常量。

const appName = 'Demo App';
const maxCount = 10;
不能这样:

const now = DateTime.now(); // 错误
因为当前时间不是编译期能确定的。

4.3 Flutter 中的 const
Flutter 里经常写:

const Text('Hello')
如果 Widget 内容固定,建议加 const,可以减少不必要的对象创建。

Column(
children: const [
Text('语文'),
Text('数学'),
],
)

  1. 基础数据类型
    5.1 int
    整数:

int count = 10;
int age = 18;
5.2 double
小数:

double price = 19.99;
double height = 175.5;
5.3 num
num 是 int 和 double 的父类型。

num a = 10;
num b = 3.14;
5.4 String
字符串:

String name = 'Tom';
String title = "首页";
字符串拼接:

String firstName = 'Tom';
String lastName = 'Lee';

String fullName = firstName + ' ' + lastName;
更推荐字符串模板:

String fullName = 'firstNamelastName';
表达式用 ${}:

int age = 18;
String text = '年龄是 ${age + 1}';
多行字符串:

String content = '''
第一行
第二行
第三行
''';
5.5 bool
布尔值:

bool isLogin = true;
bool isVip = false;

  1. 空安全 Null Safety
    Dart 默认变量不能为 null。

String name = null; // 错误
如果允许为空,要加 ?:

String? name = null;
6.1 可空类型
String? nickname;

nickname = null;
nickname = 'Tom';
使用可空变量时,不能直接当非空使用:

String? name = null;

print(name.length); // 错误
因为 name 可能是 null。

6.2 null 判断
String? name = 'Tom';

if (name != null) {
print(name.length);
}
6.3 ?? 默认值
String? name;

String displayName = name ?? '匿名用户';
如果 name 是 null,就使用 '匿名用户'。

6.4 ?. 安全访问
String? name;

print(name?.length);
如果 name 是 null,结果就是 null,不会报错。

6.5 ! 强制非空
String? name = 'Tom';

print(name!.length);
! 表示“我确定它不是 null”。

但如果实际是 null,会运行时报错:

String? name = null;

print(name!.length); // 运行时报错
所以 ! 不要乱用。

6.6 late 延迟初始化
late String token;

void init() {
token = 'abc123';
}
late 表示稍后一定会赋值。

Flutter 中常见:

late TextEditingController controller;

@override
void initState() {
super.initState();
controller = TextEditingController();
}
如果使用前没有赋值,会报错。

  1. 运算符
    7.1 算术运算
    int a = 10;
    int b = 3;

print(a + b); // 13
print(a - b); // 7
print(a * b); // 30
print(a / b); // 3.333...
print(a ~/ b); // 3,整除
print(a % b); // 1,取余
7.2 比较运算
print(a == b);
print(a != b);
print(a > b);
print(a >= b);
print(a < b);
print(a <= b);
7.3 逻辑运算
bool isLogin = true;
bool isVip = false;

print(isLogin && isVip); // 并且
print(isLogin || isVip); // 或者
print(!isLogin); // 取反
7.4 赋值运算
int count = 1;

count += 1;
count -= 1;
count *= 2;
7.5 ??=
如果变量为 null,才赋值:

String? name;

name ??= '匿名用户';

print(name); // 匿名用户

  1. 条件语句
    8.1 if else
    int score = 85;

if (score >= 90) {
print('优秀');
} else if (score >= 60) {
print('及格');
} else {
print('不及格');
}
8.2 三元表达式
bool isLogin = true;

String text = isLogin ? '已登录' : '未登录';
Flutter 中常用:

Text(isLogin ? '退出登录' : '登录')
8.3 switch
String role = 'teacher';

switch (role) {
case 'admin':
print('管理员');
break;
case 'teacher':
print('老师');
break;
default:
print('普通用户');
}

  1. 循环
    9.1 for
    for (int i = 0; i < 5; i++) {
    print(i);
    }
    9.2 for in
    List<String> names = ['Tom', 'Jerry'];

for (final name in names) {
print(name);
}
9.3 while
int count = 0;

while (count < 3) {
print(count);
count++;
}
9.4 do while
int count = 0;

do {
print(count);
count++;
} while (count < 3);

  1. List 列表
    List 类似数组。

List<String> names = ['Tom', 'Jerry', 'Alice'];
也可以简写:

final names = ['Tom', 'Jerry', 'Alice'];
10.1 常用操作
names.add('Bob');
names.remove('Tom');
names.removeAt(0);

print(names.length);
print(names[0]);
10.2 遍历
for (final name in names) {
print(name);
}
names.forEach((name) {
print(name);
});
10.3 map 转换
final upperNames = names.map((name) {
return name.toUpperCase();
}).toList();
简写:

final upperNames = names.map((name) => name.toUpperCase()).toList();
10.4 where 过滤
final longNames = names.where((name) => name.length > 3).toList();
10.5 firstWhere
final user = users.firstWhere((user) => user.id == 1);
如果可能找不到,建议:

final user = users.where((user) => user.id == 1).firstOrNull;
不过 firstOrNull 需要额外扩展包,基础 Dart 里可以这样:

User? found;

for (final user in users) {
if (user.id == 1) {
found = user;
break;
}
}

  1. Set 集合
    Set 不允许重复。

Set<int> ids = {1, 2, 3, 3};

print(ids); // {1, 2, 3}
常用:

ids.add(4);
ids.remove(2);
print(ids.contains(1));

  1. Map 字典
    Map 是键值对。

Map<String, dynamic> user = {
'id': 1,
'name': 'Tom',
'age': 18,
};
读取:

print(user['name']);
修改:

user['name'] = 'Jerry';
判断:

print(user.containsKey('name'));
遍历:

user.forEach((key, value) {
print('key:value');
});
Flutter 网络请求 JSON 经常用:

Map<String, dynamic> json = {
'username': 'tom',
'password': '123456',
};

  1. 函数
    13.1 普通函数
    int add(int a, int b) {
    return a + b;
    }
    调用:

final result = add(1, 2);
13.2 无返回值
void log(String message) {
print(message);
}
13.3 箭头函数
函数体只有一行时:

int add(int a, int b) => a + b;
等价于:

int add(int a, int b) {
return a + b;
}
13.4 可选位置参数
void sayHello(String name, [String? prefix]) {
print('{prefix ?? ''}name');
}
调用:

sayHello('Tom');
sayHello('Tom', 'Hello');
13.5 命名参数
Flutter 里大量使用命名参数。

void createUser({
required String name,
int age = 18,
}) {
print('nameage');
}
调用:

createUser(name: 'Tom');
createUser(name: 'Tom', age: 20);
required 表示必传。

默认值:

int age = 18
13.6 函数作为参数
void runTask(void Function() task) {
task();
}

runTask(() {
print('执行任务');
});
带参数:

void each(List<String> list, void Function(String item) callback) {
for (final item in list) {
callback(item);
}
}
调用:

each(['A', 'B'], (item) {
print(item);
});
这就是高阶函数。

  1. 类 class
    14.1 定义类
    class User {
    String name;
    int age;

User(this.name, this.age);

void sayHello() {
print('Hello, $name');
}
}
使用:

final user = User('Tom', 18);
user.sayHello();
14.2 命名参数构造函数
Flutter 项目里更常用:

class User {
final int id;
final String name;
final int age;

User({
required this.id,
required this.name,
required this.age,
});
}
创建:

final user = User(
id: 1,
name: 'Tom',
age: 18,
);
14.3 final 属性
class User {
final int id;
final String name;

User({
required this.id,
required this.name,
});
}
final 表示创建后不能改:

user.name = 'Jerry'; // 错误
Flutter 数据模型常用不可变对象。

14.4 方法
class User {
final String name;

User(this.name);

String getDisplayName() {
return '用户:$name';
}
}
14.5 getter
class User {
final String firstName;
final String lastName;

User(this.firstName, this.lastName);

String get fullName => 'firstNamelastName';
}
调用:

print(user.fullName);
像属性一样访问。

14.6 setter
class Counter {
int _value = 0;

set value(int newValue) {
if (newValue >= 0) {
_value = newValue;
}
}

int get value => _value;
}

  1. 私有成员
    Dart 没有 private 关键字,用 _ 开头表示库内私有。

class UserService {
String _token = '';

void _refreshToken() {
print('刷新 token');
}
}
_token 和 _refreshToken 在当前文件库外不可访问。

Flutter 里常见:

class _HomePageState extends State<HomePage> {}

  1. 继承 extends
    class Animal {
    void eat() {
    print('吃东西');
    }
    }

class Dog extends Animal {
void bark() {
print('汪汪');
}
}
使用:

final dog = Dog();
dog.eat();
dog.bark();
16.1 重写方法
class Dog extends Animal {
@override
void eat() {
print('狗在吃东西');
}
}
@override 表示重写父类方法。

Flutter 里:

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}

  1. 抽象类 abstract
    abstract class ApiService {
    Future<String> getData();
    }
    子类必须实现:

class UserService extends ApiService {
@override
Future<String> getData() async {
return 'user data';
}
}

  1. implements 接口实现
    Dart 里每个类都可以当接口。

class Logger {
void log(String message) {}
}

class ConsoleLogger implements Logger {
@override
void log(String message) {
print(message);
}
}
implements 要实现所有成员。

  1. mixin 混入
    mixin 用于复用一组方法。

mixin LoggerMixin {
void log(String message) {
print('[LOG] $message');
}
}

class UserService with LoggerMixin {
void getUser() {
log('获取用户');
}
}
Flutter 中很多状态类会用 mixin,比如动画:

class _PageState extends State<Page>
with SingleTickerProviderStateMixin {
}

  1. enum 枚举
    enum LoginStatus {
    loggedOut,
    loggingIn,
    loggedIn,
    }
    使用:

LoginStatus status = LoginStatus.loggedOut;

if (status == LoginStatus.loggedIn) {
print('已登录');
}
Flutter 中可以控制 UI 状态:

switch (status) {
case LoginStatus.loggedOut:
return LoginPage();
case LoginStatus.loggingIn:
return LoadingView();
case LoginStatus.loggedIn:
return HomePage();
}

  1. 泛型
    泛型就是把类型作为参数。

class ApiResult<T> {
final int code;
final String message;
final T data;

ApiResult({
required this.code,
required this.message,
required this.data,
});
}
使用:

final result = ApiResult<User>(
code: 200,
message: 'success',
data: user,
);
列表也是泛型:

List<String> names = [];
Map<String, dynamic> json = {};
泛型方法:

T getFirst<T>(List<T> list) {
return list.first;
}
调用:

final name = getFirst<String>(['Tom', 'Jerry']);
final age = getFirst<int>([18, 20]);

  1. Future 异步
    Flutter 网络请求、读文件、数据库、本地存储都大量使用异步。

Future<String> fetchData() async {
await Future.delayed(const Duration(seconds: 1));
return '数据';
}
调用:

void load() async {
final data = await fetchData();
print(data);
}
22.1 async / await
Future<void> login() async {
print('开始登录');

final token = await requestLogin();

print('token: $token');
}
await 只能在 async 函数里用。

22.2 try catch
Future<void> loadUser() async {
try {
final user = await fetchUser();
print(user.name);
} catch (e) {
print('请求失败:$e');
}
}

  1. Stream 流
    Stream 表示一连串异步数据。

Stream<int> countStream() async* {
for (int i = 0; i < 5; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i;
}
}
监听:

countStream().listen((value) {
print(value);
});
Flutter 中常见于:

WebSocket
蓝牙数据
定位变化
表单输入变化
Firebase 数据

  1. 异常处理
    抛异常:

throw Exception('登录失败');
捕获:

try {
await login();
} catch (e) {
print(e);
}
自定义异常:

class ApiException implements Exception {
final String message;

ApiException(this.message);

@override
String toString() => message;
}
使用:

throw ApiException('Token 已过期');

  1. import 导入
    导入系统库:

import 'dart:convert';
导入第三方包:

import 'package:dio/dio.dart';
导入项目文件:

import '../models/user.dart';
Flutter 中:

import 'package:flutter/material.dart';

  1. JSON 转模型
    后端返回 JSON:

{
"id": 1,
"name": "Tom",
"age": 18
}
Dart 模型:

class User {
final int id;
final String name;
final int age;

User({
required this.id,
required this.name,
required this.age,
});

factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'],
name: json['name'] ?? '',
age: json['age'] ?? 0,
);
}

Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'age': age,
};
}
}
使用:

final user = User.fromJson(response.data);
final json = user.toJson();
列表转换:

final users = (data as List)
.map((item) => User.fromJson(item))
.toList();
更严谨一点:

final users = (data as List<dynamic>)
.map((item) => User.fromJson(item as Map<String, dynamic>))
.toList();

  1. Flutter 中最常见的 Dart 写法
    27.1 StatelessWidget
    class HomePage extends StatelessWidget {
    const HomePage({super.key});

@override
Widget build(BuildContext context) {
return const Text('首页');
}
}
解释:

class HomePage extends StatelessWidget
定义一个无状态组件。

const HomePage({super.key});
构造函数,传递 key 给父类。

Widget build(BuildContext context)
返回 UI。

27.2 StatefulWidget
class CounterPage extends StatefulWidget {
const CounterPage({super.key});

@override
State<CounterPage> createState() => _CounterPageState();
}

class _CounterPageState extends State<CounterPage> {
int count = 0;

@override
Widget build(BuildContext context) {
return Column(
children: [
Text('数量:$count'),
ElevatedButton(
onPressed: () {
setState(() {
count++;
});
},
child: const Text('增加'),
),
],
);
}
}
这里涉及:

类
继承
泛型
私有类
状态变量
回调函数
setState
Widget 树

  1. 常见 Widget 参数语法
    Flutter 大量使用命名参数。

Container(
width: 100,
height: 100,
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(top: 20),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
),
child: const Text('Hello'),
)
这些都是命名参数:

width:
height:
padding:
margin:
decoration:
child:
child 表示一个子组件。

children 表示多个子组件:

Column(
children: const [
Text('A'),
Text('B'),
],
)

  1. 回调函数语法
    按钮点击:

ElevatedButton(
onPressed: () {
print('点击');
},
child: const Text('提交'),
)
onPressed 接收一个函数。

如果按钮禁用:

ElevatedButton(
onPressed: null,
child: const Text('提交'),
)
带参数的回调:

TextField(
onChanged: (value) {
print(value);
},
)

  1. async 在 UI 中的使用
    ElevatedButton(
    onPressed: () async {
    final result = await login();
    print(result);
    },
    child: const Text('登录'),
    )
    网络请求:

Future<void> loadData() async {
try {
final user = await UserService.getUserInfo();

setState(() {
  this.user = user;
});

} catch (e) {
setState(() {
errorMessage = e.toString();
});
}
}

  1. 扩展方法 extension
    可以给已有类型扩展方法。

extension StringExt on String {
bool get isPhone {
return RegExp(r'^1\d{10}$').hasMatch(this);
}
}
使用:

final phone = '13800138000';

print(phone.isPhone);
Flutter 项目里可用于格式化:

extension DateTimeExt on DateTime {
String get yyyyMMdd {
return 'year-month-$day';
}
}

  1. typedef 类型别名
    给函数类型起别名。

typedef ValueChanged<T> = void Function(T value);
自定义:

typedef LoginCallback = void Function(String token);
使用:

class LoginButton {
final LoginCallback onLogin;

LoginButton({required this.onLogin});
}
Flutter 内部也大量使用类似写法。

  1. cascade 级联操作符 ..
    可以连续操作同一个对象。

final list = <String>[]
..add('A')
..add('B')
..add('C');
等价于:

final list = <String>[];
list.add('A');
list.add('B');
list.add('C');
对象配置:

final dio = Dio()
..options.baseUrl = 'https://api.example.com'
..options.connectTimeout = const Duration(seconds: 10);

  1. as / is 类型判断
    34.1 is
    if (value is String) {
    print(value.length);
    }
    34.2 as
    final map = data as Map<String, dynamic>;
    如果类型不对,会报错。

安全点可以先判断:

if (data is Map<String, dynamic>) {
print(data['name']);
}

  1. Dart 在 Flutter 里的学习重点
    如果你是为了 Flutter,优先掌握这些:

变量:var / final / const
空安全:? / ?? / ?. / !
函数:命名参数、required、回调函数
类:构造函数、final 属性、fromJson
集合:List / Map / Set
异步:Future / async / await / try catch
泛型:List<T> / ApiResult<T>
继承:extends StatelessWidget / StatefulWidget
状态:setState
导入:import
最小综合例子

import 'package:flutter/material.dart';

class User {
final int id;
final String name;

User({
required this.id,
required this.name,
});

factory User.fromJson(Map<String, dynamic> json) {
return User(
id: json['id'] ?? 0,
name: json['name'] ?? '',
);
}
}

Future<User> fetchUser() async {
await Future.delayed(const Duration(seconds: 1));

final json = {
'id': 1,
'name': 'Tom',
};

return User.fromJson(json);
}

class UserPage extends StatefulWidget {
const UserPage({super.key});

@override
State<UserPage> createState() => _UserPageState();
}

class _UserPageState extends State<UserPage> {
User? user;
bool loading = false;

@override
void initState() {
super.initState();
loadUser();
}

Future<void> loadUser() async {
setState(() {
loading = true;
});

final result = await fetchUser();

setState(() {
  user = result;
  loading = false;
});

}

@override
Widget build(BuildContext context) {
if (loading) {
return const CircularProgressIndicator();
}

return Text(user?.name ?? '暂无用户');

}
}
这个例子覆盖了 Flutter 开发最常见的 Dart 语法:

import
class
final
构造函数
factory
Map
Future
async/await
StatefulWidget
泛型 State<UserPage>
可空类型 User?
setState
?? 默认值
学 Flutter 的 Dart,不需要一开始钻特别深的语言细节。先把这些语法吃透,就可以开始写页面、调接口、做登录、做列表和详情页了。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容