在本篇文章中,我們將通過一個(gè)實(shí)際的 Flutter 應(yīng)用來綜合運(yùn)用最近學(xué)到的知識(shí),包括保存到數(shù)據(jù)庫、進(jìn)行 HTTP 請(qǐng)求等。我們將開發(fā)一個(gè)簡(jiǎn)單的天氣應(yīng)用,可以根據(jù)用戶輸入的城市名獲取該城市的天氣信息,并將用戶查詢的城市列表保存到本地?cái)?shù)據(jù)庫中。
第一步:需求分析和設(shè)計(jì)
1. 確定項(xiàng)目目標(biāo)
我們的目標(biāo)是開發(fā)一個(gè)天氣應(yīng)用,用戶可以在應(yīng)用中輸入城市名,然后獲取該城市的天氣信息。
2. 設(shè)計(jì)界面
我們的應(yīng)用包含兩個(gè)頁面:主頁面用于輸入城市名,顯示天氣信息,以及查詢歷史記錄頁面用于顯示用戶查詢的城市列表。
第二步:開發(fā)
1. 創(chuàng)建 Flutter 項(xiàng)目
首先,在命令行中創(chuàng)建一個(gè)新的 Flutter 項(xiàng)目:
flutter create my_first_flutter_app
然后,進(jìn)入項(xiàng)目目錄:
cd my_first_flutter_app
2. 編碼實(shí)現(xiàn)
a. 創(chuàng)建頁面和路由
在 lib 文件夾中創(chuàng)建兩個(gè)文件:home_page.dart、history_page.dart。
home_page.dart:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String city = '';
String weather = '';
void getWeather() async {
final response = await http.get(Uri.parse(
'https://api.openweathermap.org/data/2.5/weather?q=$city&appid=YOUY_API_KEY'));
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
setState(() {
weather =
'Temperature: ${data['main']['temp']}°C, Weather: ${data['weather'][0]['main']}';
});
} else {
setState(() {
weather = 'Failed to get weather data';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Weather App'),
),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
onChanged: (value) {
setState(() {
city = value;
});
},
decoration: InputDecoration(labelText: 'City Name'),
),
ElevatedButton(
onPressed: () {
getWeather();
},
child: Text('Get Weather'),
),
SizedBox(height: 20),
Text(
weather,
style: TextStyle(fontSize: 18),
),
],
),
),
);
}
}
history_page.dart:
import 'package:flutter/material.dart';
import 'package:my_first_flutter_app/database_helper.dart';
import 'package:my_first_flutter_app/city.dart';
class HistoryPage extends StatefulWidget {
@override
_HistoryPageState createState() => _HistoryPageState();
}
class _HistoryPageState extends State<HistoryPage> {
List<City> cities = [];
@override
void initState() {
super.initState();
fetchCities();
}
void fetchCities() async {
final dbHelper = DatabaseHelper.instance;
final allRows = await dbHelper.queryAllRows();
setState(() {
cities = allRows.map((row) => City.fromMap(row)).toList();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Search History'),
),
body: ListView.builder(
itemCount: cities.length,
itemBuilder: (context, index) {
final city = cities[index];
return ListTile(
title: Text(city.name),
subtitle: Text('Weather: ${city.weather}'),
);
},
),
);
}
}
在 main.dart 文件中,設(shè)置路由:
import 'package:flutter/material.dart';
import 'package:my_first_flutter_app/home_page.dart';
import 'package:my_first_flutter_app/history_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomePage(),
'/history': (context) => HistoryPage(),
},
);
}
}
b. 實(shí)現(xiàn)數(shù)據(jù)庫功能
我們將使用 SQLite 來保存用戶查詢的城市列表。在 lib 文件夾中創(chuàng)建新的文件 city.dart、database_helper.dart,用于創(chuàng)建和管理數(shù)據(jù)庫。
city.dart
class City {
int id;
String name;
String weather;
City({this.id = 0, required this.name, required this.weather});
Map<String, dynamic> toMap() {
return {'id': id, 'name': name, 'weather': weather};
}
City.fromMap(Map<String, dynamic> map)
: id = map['id'],
name = map['name'],
weather = map['weather'];
}
database_helper.dart
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'package:my_first_flutter_app/city.dart';
class DatabaseHelper {
static final _databaseName = 'weather_database.db';
static final _databaseVersion = 1;
static final table = 'cities';
static final columnId = '_id';
static final columnName = 'name';
static final columnWeather = 'weather';
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance = DatabaseHelper._privateConstructor();
static Database? _database;
Future<Database?> get database async {
if (_database != null) return _database;
_database = await _initDatabase();
return _database;
}
_initDatabase() async {
String path = join(await getDatabasesPath(), _databaseName);
return await openDatabase(path,
version: _databaseVersion, onCreate: _onCreate);
}
Future<void> _onCreate(Database db, int version) async {
await db.execute('''
CREATE TABLE $table (
$columnId INTEGER PRIMARY KEY,
$columnName TEXT NOT NULL,
$columnWeather TEXT NOT NULL
)
''');
}
Future<int> insert(City city) async {
Database? db = await instance.database;
return await db?.insert(table, city.toMap()) ?? 0;
}
Future<List<Map<String, dynamic>>> queryAllRows() async {
Database? db = await instance.database;
return await db?.query(table) ?? [];
}
}
第三步:測(cè)試
1. 運(yùn)行應(yīng)用
使用以下命令在模擬器或真機(jī)上運(yùn)行應(yīng)用:
flutter run
檢查應(yīng)用是否按預(yù)期工作,并確保你可以查詢城市的天氣,并查看查詢歷史記錄。
2. 進(jìn)行單元測(cè)試和集成測(cè)試
除了手動(dòng)測(cè)試之外,我們還應(yīng)該進(jìn)行單元測(cè)試和集成測(cè)試來確保應(yīng)用的穩(wěn)定性和正確性。在 Flutter 中,我們可以使用 flutter_test 包進(jìn)行測(cè)試。
第四步:發(fā)布
當(dāng)我們完成了開發(fā)和測(cè)試之后,就可以考慮發(fā)布應(yīng)用了。在發(fā)布之前,我們需要完成以下幾個(gè)步驟:
1. 生成 APK 或 IPA 文件
使用以下命令生成 APK 文件(Android)或 IPA 文件(iOS):
flutter build apk
flutter build ios
2. 申請(qǐng)開發(fā)者賬號(hào)
如果你要發(fā)布到應(yīng)用商店(如 Google Play 或 App Store),你需要申請(qǐng)開發(fā)者賬號(hào),并遵循相應(yīng)的發(fā)布指南。
3. 提交應(yīng)用
一旦你準(zhǔn)備好了 APK 或 IPA 文件,并且已經(jīng)申請(qǐng)了開發(fā)者賬號(hào),你可以提交應(yīng)用到相應(yīng)的應(yīng)用商店進(jìn)行審核和發(fā)布。
總結(jié)
在本篇文章中,我們通過一個(gè)簡(jiǎn)單的天氣應(yīng)用示例,綜合運(yùn)用了最近學(xué)到的知識(shí),包括保存到數(shù)據(jù)庫、進(jìn)行 HTTP 請(qǐng)求等。通過這個(gè)實(shí)戰(zhàn)項(xiàng)目,你可以更加深入地了解 Flutter 應(yīng)用的開發(fā)流程,并掌握實(shí)際項(xiàng)目中的常用技術(shù)和最佳實(shí)踐。文章來源:http://www.zghlxwxcb.cn/news/detail-636044.html
希望這個(gè)實(shí)戰(zhàn)項(xiàng)目對(duì)你有所幫助。如果你有任何問題或需要進(jìn)一步的指導(dǎo),請(qǐng)隨時(shí)向我詢問。祝你在 Flutter 開發(fā)的道路上取得成功!文章來源地址http://www.zghlxwxcb.cn/news/detail-636044.html
到了這里,關(guān)于Flutter系列文章-實(shí)戰(zhàn)項(xiàng)目的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!