前言 🌟
Flutter的灵活性和强大性使其成为跨平台应用程序开发的热门选择。在这篇博客中,我们将通过构建一个简单而实用的World Time应用程序,深入了解Flutter的核心概念。从页面小部件到异步方法,再到自定义类的使用,让我们一起踏上这段富有启发性的Flutter之旅。
启动World Time应用程序 🌍⏰
创建页面小部件 🛠️
- 创建
lib/pages
文件夹,用于存放页面小部件。 - 创建
home.dart
、choose_location.dart
和loading.dart
文件。 - 在每个文件中创建基本的Stateful Widget,构建简单的UI。
// home.dart
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Text('Home Screen'),
),
);
}
}
// choose_location.dart
import 'package:flutter/material.dart';
class ChooseLocation extends StatefulWidget {
_ChooseLocationState createState() => _ChooseLocationState();
}
class _ChooseLocationState extends State<ChooseLocation> {
Widget build(BuildContext context) {
return Scaffold(
body: Text('Choose Location Screen'),
);
}
}
// loading.dart
import 'package:flutter/material.dart';
class Loading extends StatefulWidget {
_LoadingState createState() => _LoadingState();
}
在main.dart
中导入这些页面小部件 🚀
import 'package:flutter/material.dart';
import 'package:world_time/pages/home.dart';
import 'package:world_time/pages/choose_location.dart';
import 'package:world_time/pages/loading.dart';
void main() {
runApp(MaterialApp(
home: Home(),
));
}
创建基本路由 🗺️
- 在
MaterialApp
中创建routes
属性,其值是一个Map,包含不同路由的命名和对应的函数。 - 函数的参数是
context
,返回要加载的Widget。 - 使用
Navigator.pushNamed
进行路由导航。 - 使用
Navigator.pop
在栈上弹出当前路由。
MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => Loading(),
'/home': (context) => Home(),
'/location': (context) => ChooseLocation(),
},
);
在定义路由表时,不应该在每个路由定义的末尾使用分号 ;而应该使用逗号 ,
'/home'
是一个字符串,而 '/home': (context) => Home()
是一个 Dart 映射(Map)中的一个键值对,键是字符串 '/home'
,值是一个 Dart 函数。
导航到新路由 🛤️
在选择位置的屏幕中,使用Navigator.pushNamed
导航到新的路由(Choose Location)。
TextButton.icon(
onPressed: () {
Navigator.pushNamed(context, '/location');
},
icon: Icon(Icons.edit_location),
label: Text('Edit Location'),
)
在 Flutter 中,导航通常涉及使用 Navigator
来管理页面(Route
)的堆栈,而 Navigator
的 push
方法期望接受一个 Route
对象而不是直接的字符串。
在新路由中添加AppBar 🌐
在选择位置的屏幕中,通过添加AppBar
提供返回上一页的功能。
Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue[900],
title: Text('Choose a Location'),
centerTitle: true,
elevation: 0,
),
backgroundColor: Colors.grey[200],
// Other content...
)
路由的压栈与出栈 🔄
- Flutter应用程序中,路由可以想象为屏幕的栈,通过
Navigator.pushNamed
压入新路由,通过Navigator.pop
出栈。 - 出栈时,可以返回到前一个路由,即前一个屏幕。
使用initState和setState 🔄
在ChooseLocation
页面中,演示使用initState
和setState
class _ChooseLocationState extends State<ChooseLocation> {
int counter = 0;
void initState() {
super.initState();
print('initState function ran');
}
Widget build(BuildContext context) {
print('build function ran');
return Scaffold(
appBar: AppBar(
title: Text('Choose a Location'),
),
body: Center(
child: RaisedButton(
onPressed: () {
setState(() {
counter += 1;
});
print('Counter is $counter');
},
child: Text('Counter is $counter'),
),
),
);
}
}
World Time自定义类 🌐⏰
创建WorldTime
类 🌐
- 在
lib
文件夹下创建一个名为services
的新文件夹,用于存放服务类。 - 在
services
文件夹下创建一个名为world_time.dart
的新Dart文件,用于存放WorldTime
类。 - 在
world_time.dart
文件中导入所需的包:http
和dart:convert
。 - 创建
WorldTime
类,包含location
、time
、flag
和URL
属性。
import 'package:http/http.dart' as http;
import 'dart:convert';
class WorldTime {
String location;
String time;
String flag;
String URL;
WorldTime({
required this.location,
required this.flag,
required this.URL,
});
Future<void> getTime() async {
// 之前的逻辑...
// 设置time属性
time = now.toString();
}
}
将逻辑移动到WorldTime
类 🚚
- 将原先
get time
函数中的逻辑移动到WorldTime
类中。 - 在
WorldTime
类中,使用await
等关键字使函数变为异步方法。 - 在
get time
函数中设置time
属性,以便在使用WorldTime
实例时获取时间。
Future<void> getTime() async {
http.Response response = await http.get(URL);
Map<String, dynamic> data = jsonDecode(response.body);
// 原先的逻辑...
// 设置time属性
time = now.toString();
}
使用WorldTime
类 🌐
- 在加载屏幕(loading.dart)中导入
WorldTime
类。 - 创建
setupWorldTime
函数,用于实例化WorldTime
并获取时间。 - 使用`
set state`更新UI以显示获取到的时间。
class _LoadingState extends State<Loading> {
String time = 'Loading';
void setupWorldTime() async {
WorldTime instance = WorldTime(
location: 'Berlin',
flag: 'Germany.png',
URL: '/Europe/Berlin',
);
await instance.getTime();
// 使用 set state 更新 UI
setState(() {
time = instance.time;
});
}
void initState() {
super.initState();
setupWorldTime();
}
// 构建 UI...
}
World Time应用程序启动成功 🎉
你已经成功地创建了World Time应用程序的基本框架,并使用自定义的WorldTime
类获取了实际时间数据。通过路由、异步方法和状态管理,我们建立了一个简单而强大的Flutter应用程序。🚀
结语 🌐⏰
通过完成World Time应用程序的搭建,我们不仅学到了如何使用Flutter创建应用,还深入了解了UI构建、路由管理、异步编程等关键概念。这只是Flutter学习之旅的开端,希望你能以这为起点,持续挑战更高级的主题,成为精湛的Flutter开发者。感谢你的阅读,愿你在这个技术的舞台上取得卓越的成就!🚀