Flutter是Google推出的开源UI工具包,用于从单一代码库构建原生编译的移动、Web和桌面应用。其核心优势在于:
# macOS/Linux
git clone https://github.com/flutter/flutter.git -b stable
export PATH="$PATH:`pwd`/flutter/bin"
# Windows
# 下载Flutter SDK压缩包并解压到指定目录
# 将flutter\bin添加到系统环境变量PATH中
flutter doctor
flutter create my_first_app
cd my_first_app
flutter run
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@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({super.key, required this.title});
final String title;
@override
State createState() => _MyHomePageState();
}
class _MyHomePageState extends State {
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: [
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),
),
);
}
}
Flutter应用是由Widget构成的树状结构:
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My App'),
),
body: Center(
child: Column(
children: [
Text('Hello'),
ElevatedButton(
onPressed: () {},
child: Text('Click me'),
),
],
),
),
),
)
// 无状态组件
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text('I cannot change!');
}
}
// 有状态组件
class MyStatefulWidget extends StatefulWidget {
@override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State {
int _count = 0;
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
setState(() {
_count++;
});
},
child: Text('Clicked $_count times'),
);
}
}
方案 | 适用场景 | 复杂度 |
---|---|---|
setState | 局部状态 | 低 |
InheritedWidget | 跨组件共享 | 中 |
Provider | 应用级状态 | 中 |
Bloc/Riverpod | 复杂应用 | 高 |
Redux | 大型应用 | 高 |
Column(
children: [
Container(
padding: EdgeInsets.all(20),
margin: EdgeInsets.only(bottom: 10),
color: Colors.blue,
child: Row(
children: [
Icon(Icons.star, color: Colors.amber),
SizedBox(width: 10),
Expanded(
child: Text(
'Flutter is awesome!',
style: TextStyle(color: Colors.white),
),
),
],
),
),
Expanded(
child: GridView.count(
crossAxisCount: 2,
children: List.generate(10, (index) {
return Card(
child: Center(
child: Text('Item $index'),
),
);
}),
),
),
],
)
class CustomButton extends StatelessWidget {
final String text;
final VoidCallback onPressed;
final Color color;
const CustomButton({
required this.text,
required this.onPressed,
this.color = Colors.blue,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
style: ElevatedButton.styleFrom(
primary: color,
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
onPressed: onPressed,
child: Text(
text,
style: TextStyle(fontSize: 18),
),
);
}
}
// 使用
CustomButton(
text: 'Sign In',
color: Colors.green,
onPressed: () {
print('Button pressed');
},
)
import 'dart:convert';
import 'package:http/http.dart' as http;
Future fetchPost() async {
final response = await http.get(
Uri.parse('https://jsonplaceholder.typicode.com/posts/1'),
);
if (response.statusCode == 200) {
return Post.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load post');
}
}
class Post {
final int userId;
final int id;
final String title;
final String body;
Post({
required this.userId,
required this.id,
required this.title,
required this.body,
});
factory Post.fromJson(Map json) {
return Post(
userId: json['userId'],
id: json['id'],
title: json['title'],
body: json['body'],
);
}
}
pubspec.yaml
添加依赖:
dependencies:
json_annotation: ^4.8.0
dev_dependencies:
build_runner: ^2.3.3
json_serializable: ^6.5.4
定义模型:
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User {
final String name;
final String email;
final int age;
User({
required this.name,
required this.email,
required this.age,
});
factory User.fromJson(Map json) => _$UserFromJson(json);
Map toJson() => _$UserToJson(this);
}
生成代码:
flutter pub run build_runner build
// 定义路由
MaterialApp(
routes: {
'/': (context) => HomePage(),
'/details': (context) => DetailsPage(),
},
);
// 导航到新页面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => DetailsPage()),
);
// 返回
Navigator.pop(context);
// 定义带参数的路由
MaterialApp(
routes: {
'/details': (context) => DetailsPage(
item: ModalRoute.of(context)!.settings.arguments as Item,
),
},
);
// 传递参数
Navigator.pushNamed(
context,
'/details',
arguments: item,
);
// Flutter端
import 'package:flutter/services.dart';
class BatteryLevel {
static const MethodChannel _channel =
MethodChannel('samples.flutter.dev/battery');
static Future getBatteryLevel() async {
final int level = await _channel.invokeMethod('getBatteryLevel');
return level;
}
}
// Android端 (Kotlin)
val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger,
"samples.flutter.dev/battery")
channel.setMethodCallHandler { call, result ->
when (call.method) {
"getBatteryLevel" -> {
val batteryLevel = getBatteryLevel()
if (batteryLevel != -1) {
result.success(batteryLevel)
} else {
result.error("UNAVAILABLE", "Battery level not available.", null)
}
}
else -> result.notImplemented()
}
}
// iOS端 (Swift)
let controller = window?.rootViewController as! FlutterViewController
let channel = FlutterMethodChannel(name: "samples.flutter.dev/battery",
binaryMessenger: controller.binaryMessenger)
channel.setMethodCallHandler { call, result in
guard call.method == "getBatteryLevel" else {
result(FlutterMethodNotImplemented)
return
}
self.receiveBatteryLevel(result: result)
}
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/counter.dart';
void main() {
test('Counter value should be incremented', () {
final counter = Counter();
counter.increment();
expect(counter.value, 1);
});
}
class Counter {
int value = 0;
void increment() => value++;
void decrement() => value--;
}
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/main.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
await tester.pumpWidget(const MyApp());
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
});
}
flutter build appbundle
# 生成的bundle文件位于 build/app/outputs/bundle/release/app.aab
flutter build ipa
# 生成的ipa文件位于 build/ios/ipa
插件 | 功能 |
---|---|
http | 网络请求 |
provider | 状态管理 |
shared_preferences | 本地存储 |
sqflite | 数据库 |
camera | 相机访问 |
geolocator | 地理位置 |
firebase_core | Firebase集成 |
flutter_bloc | BLoC模式实现 |
Flutter通过其高效的渲染引擎和丰富的组件库,为开发者提供了构建高质量跨平台应用的强大工具。本文涵盖了从环境搭建到应用发布的全流程,重点介绍了:
随着Flutter的持续发展,其生态系统也在不断壮大。建议开发者:
Flutter的学习曲线可能较陡峭,但一旦掌握,将极大提升开发效率和用户体验一致性。