Tải bản đầy đủ (.pdf) (31 trang)

Bài tập nhóm môn lập trình thiết bị di động đề tài xây dựng ứng dụng dự báo thời tiết

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (610.53 KB, 31 trang )

lOMoARcPSD|11346942

BỘ GIÁO DỤC VÀ ĐÀO TẠO
TRƯỜNG ĐẠI HỌC NHA TRANG
KHOA CÔNG NGHỆ THÔNG TIN



BÀI TẬP NHÓM
ĐỀ TÀI: XÂY DỰNG ỨNG DỤNG DỰ BÁO THỜI TIẾT

MƠN: LẬP TRÌNH THIẾT BỊ DI ĐỘNG
Giáo viên: Huỳnh Tuấn Anh
Lớp học phần: 62.CNTT-1
Thành viên nhóm:

Nguyễn Hoàng Đăng Quang – 62134138
Phạm Huỳnh Đức Vinh - 62132711
Trương Tuấn Lộc - 62131020
Niên khóa: 2022 – 2023

lOMoARcPSD|11346942

NHẬN XÉT CỦA GIÁO VIÊN
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................


.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................
.........................................................................................................................................

lOMoARcPSD|11346942

Mục Lục

Chương 1. TỔNG QUAN ĐỀ TÀI............................................................4
1.1.GIỚI THIỆU CHUNG VỀ LĨNH VỰC NGHIÊN CỨU............................4

1.1.1...............................................Giới thiệu về các ứng dụng dự báo thời tiết
4


1.1.2..................................................................................Giới thiệu sơ lược về Flutter
7

Chương 2. CƠ SỞ LÝ THUYẾT..............................................................8
2.1. Giới thiệu công cụ và thư viện cần thiết.....................................8

2.1.1. OpenWeather API....................................................................8
2.1.2. Thư viện Intl............................................................................8
2.1.3.Thư viện http............................................................................9
Chương 3. XÂY DỰNG ỨNG DỤNG.....................................................10
3.1. Model.........................................................................................10
3.1.1 Hour_Forecast_model.dart......................................................10
3.1.2. Weather_model.dart..............................................................12
3.2. Page...........................................................................................13
3.2.1. WeatherPage.dart..................................................................13
3.2.2. SearchPage.dart....................................................................19
3.3. Provider......................................................................................22
3.3.1. ...............................................................................................WeatherProvider.dart

22
3.4. Services......................................................................................22

3.4.1. Weather_API_Service.dart.....................................................22
3.5. Widget........................................................................................23

3.5.1. Current_Weather.dart............................................................23
3.5.2. DailyList_Widget.dart............................................................24
3.5.3. MyList.dart............................................................................26
3.6. WeatherApp.dart........................................................................28

Chương 4. Giao diện ứng dụng và kết luận.......................................29
4.1. Giao diện ứng dụng...................................................................29
4.2. Kết luận......................................................................................30

lOMoARcPSD|11346942

Chương 1. TỔNG QUAN ĐỀ TÀI

1.1. GIỚI THIỆU CHUNG VỀ LĨNH VỰC NGHIÊN CỨU
1.1.1. Giới thiệu về các ứng dụng dự báo thời tiết
Hiện nay, có nhiều phần mềm dự báo thời tiết đa dạng và phong phú, giúp người dùng
truy cập và nhận thông tin về thời tiết một cách thuận tiện và chính xác. Dưới đây là một
số phần mềm dự báo thời tiết phổ biến và đáng chú ý:

1. AccuWeather: AccuWeather là một trong những ứng dụng dự báo thời tiết phổ
biến nhất. Với khả năng cung cấp thông tin thời tiết chi tiết và chính xác,
AccuWeather có giao diện trực quan và tính năng cung cấp dự báo trong tương lai
gần và xa.

Hình 1- AccuWeather
2. The Weather Channel: The Weather Channel là một phần mềm dự báo thời tiết
đáng tin cậy, kết hợp cả dữ liệu từ các nguồn thời tiết đáng tin cậy và các chuyên gia thời
tiết. Với các tính năng như radar thời tiết, cảnh báo thời tiết và thơng báo cập nhật tức thì,
người dùng có thể ln cập nhật về điều kiện thời tiết mới nhất.

lOMoARcPSD|11346942

Hình 2 – The Weather Channel
3. Weather Underground: Weather Underground là một cộng đồng dự báo thời tiết
trực tuyến, nơi người dùng có thể chia sẻ thông tin và dự báo về thời tiết tại khu vực của

họ. Phần mềm này cung cấp thông tin chi tiết và đáng tin cậy về nhiệt độ, độ ẩm, gió,
mưa và nhiều yếu tố thời tiết khác.

Hình 3 – Weather Underground

lOMoARcPSD|11346942

4. Dark Sky: Dark Sky là một ứng dụng dự báo thời tiết nổi tiếng với khả năng dự báo
chính xác trong tương lai gần. Đặc điểm nổi bật của Dark Sky là khả năng cung cấp
thông báo cập nhật thời tiết tức thì và cảnh báo về mưa trong vòng một giờ tiếp theo.

Hình 4 – Ứng dụng Dark Sky Weather
5. WeatherBug: WeatherBug là một ứng dụng dự báo thời tiết đa nền tảng với tính
năng theo dõi thời tiết theo thời gian thực. Nó cung cấp thơng tin chi tiết về nhiệt độ, gió,
áp suất khơng khí và điều kiện thời tiết tại nhiều địa điểm trên thế giới.

Hình 5 – WeatherBug
Những phần mềm dự báo thời tiết trên đây là chỉ một số ví dụ. Hiện nay, thị trường cung
cấp nhiều sự lựa chọn cho người dùng để truy cập thông tin thời tiết và lên kế hoạch cho
các hoạt động dựa trên dự báo đáng tin cậy.
Do đó nhóm chúng em quyết định thực hiện xây dựng giao diện ứng dụng và mô tả cách
thức hoạt động của ứng dụng dự báo thời tiết

lOMoARcPSD|11346942

1.1.2. Giới thiệu sơ lược về Flutter
Flutter là một framework mã nguồn mở, nổi tiếng được phát triển bởi Google, Flutter
giúp xây dựng các ứng dụng di động nhanh chóng và hiệu quả trên cả iOS và Android từ
một mã nguồn duy nhất.


Hình 6 - Flutter
Với Flutter, nhà phát triển có thể viết mã một lần và triển khai ứng dụng trên nhiều nền
tảng một cách dễ dàng. Điều này giúp giảm đáng kể thời gian và công sức phát triển,
đồng thời tạo ra các ứng dụng đa nền tảng chất lượng cao. Không cần phải viết lại mã
nguồn cho từng nền tảng, Flutter cho phép nhà phát triển tập trung vào việc xây dựng trải
nghiệm người dùng tốt nhất.
Flutter cũng được đánh giá là dễ học. Với sử dụng ngơn ngữ lập trình Dart, một ngơn ngữ
đơn giản và dễ tiếp cận, nhà phát triển mới có thể nhanh chóng làm quen với Flutter và
bắt đầu xây dựng ứng dụng. Flutter cung cấp tài liệu phong phú, ví dụ và ví dụ thực tế
giúp người học hiểu rõ cách sử dụng framework và xây dựng ứng dụng từ đầu.
Điểm mạnh nổi bật khác của Flutter là tốc độ. Với sử dụng công nghệ gọi là "Hot
Reload", Flutter cho phép nhà phát triển thấy ngay lập tức các thay đổi được áp dụng
trong ứng dụng mà không cần phải tải lại toàn bộ ứng dụng. Điều này giúp tăng nhanh
quá trình phát triển và kiểm tra, cho phép nhà phát triển chỉnh sửa và cải thiện ứng dụng
một cách nhanh chóng và linh hoạt.

lOMoARcPSD|11346942

Tóm lại, Flutter là một framework mạnh mẽ và linh hoạt, mang lại những lợi ích đáng kể
như tốc độ, dễ học và khả năng đa nền tảng. Đây là một công cụ tuyệt vời cho nhà phát
triển ứng dụng di động để xây dựng các ứng dụng tương tác, đẹp mắt và hiệu quả trên cả
iOS và Android.

Chương 2. CƠ SỞ LÝ THUYẾT

2.1. Giới thiệu công cụ và thư viện cần thiết
2.1.1. OpenWeather API
OpenWeather và API của nó đóng vai trị quan trọng trong việc cung cấp thơng tin thời
tiết chính xác và đáng tin cậy cho các nhà phát triển và ứng dụng trên toàn thế giới.
OpenWeather là một dịch vụ hàng đầu trong lĩnh vực dự báo thời tiết, và API của nó cung

cấp một cách tiếp cận dễ dàng và mạnh mẽ để truy xuất dữ liệu thời tiết thông qua giao
diện lập trình ứng dụng.

Với OpenWeather API, ta có khả năng lấy thông tin thời tiết hiện tại, dự báo trong tương
lai và thời tiết lịch sử cho bất kỳ địa điểm nào trên thế giới. Dữ liệu thời tiết được cung
cấp bởi OpenWeather được cập nhật thường xuyên từ các nguồn đáng tin cậy, đảm bảo
rằng ứng dụng của ta sẽ ln cung cấp thơng tin chính xác và đáng tin cậy về thời tiết cho
người dùng.

API của OpenWeather hỗ trợ các định dạng phản hồi như JSON và XML, cho phép ta dễ
dàng xử lý dữ liệu và tích hợp vào ứng dụng của ta. Bằng cách sử dụng API này, ta có thể
hiển thị thơng tin thời tiết trực quan trên giao diện người dùng, tạo biểu đồ thời tiết, cung
cấp dự báo và lời khuyên về trang phục, hoặc sử dụng dữ liệu thời tiết để thực hiện các
chức năng khác như kế hoạch hàng ngày.

2.1.2. Thư viện Intl
Thư viện intl.dart là một thư viện quan trọng trong Flutter để làm việc với quốc tế hóa
(internationalization) và định dạng ngơn ngữ (localization). Nó cung cấp các công cụ
mạnh mẽ để dịch chuỗi, định dạng số và ngày tháng theo ngôn ngữ và quy tắc định dạng
cụ thể. Dưới đây là một số chi tiết về chức năng định dạng ngày tháng trong thư viện
intl.dart:

lOMoARcPSD|11346942

1. DateFormat:
- DateFormat cho phép ta định dạng ngày tháng theo ngôn ngữ và vùng địa lý cụ thể.

Bạn có thể sử dụng các ký tự đặc biệt để xác định định dạng ngày tháng, ví dụ:
dd/MM/yyyy để hiển thị ngày/tháng/năm.


- Thư viện hỗ trợ một số định dạng ngày tháng phổ biến như DateFormat.yMd()
(ngày/tháng/năm), DateFormat.Hm() (giờ:phút), DateFormat.yMMMMd() (ngày tháng
năm dài).
2. DateTimeFormat:

- DateTimeFormat giúp ta định dạng ngày tháng theo các tùy chọn ngôn ngữ và vùng
địa lý. Bạn có thể xác định các thành phần cụ thể như ngày, tháng, năm, giờ, phút và giây
để hiển thị theo cú pháp mong muốn.

- Ví dụ: DateTimeFormat(locale).format(dateTime) sẽ định dạng ngày tháng theo quy
tắc định dạng của ngôn ngữ và vùng địa lý.
Với thư viện intl.dart, ta có thể định dạng ngày tháng theo ngơn ngữ và vùng địa lý cụ
thể, làm cho ứng dụng của ta dễ dàng tương thích với người dùng trên tồn cầu.

2.1.3.Thư viện http
Thư viện http.dart trong Flutter cung cấp các công cụ để thực hiện các yêu cầu HTTP và
tương tác với các REST API. Nó là một thư viện mạnh mẽ và linh hoạt, cho phép ta gửi
yêu cầu HTTP, nhận phản hồi và xử lý dữ liệu trả về từ các dịch vụ web.
Các tính năng quan trọng của http.dart trong việc làm việc với REST API bao gồm:
1. Gửi yêu cầu HTTP: Bạn có thể sử dụng lớp http.Client để gửi các yêu cầu HTTP như
GET, POST, PUT, DELETE và PATCH đến các REST API. Với http.Client, ta có thể xác
định URL, tham số, tiêu đề và nội dung yêu cầu.
2. Xử lý phản hồi: http.dart cho phép ta nhận phản hồi từ REST API và xử lý dữ liệu trả
về. Bạn có thể truy cập các thành phần của phản hồi như mã trạng thái, tiêu đề và nội
dung để xử lý dữ liệu dễ dàng.

lOMoARcPSD|11346942

3. Định dạng dữ liệu: Thư viện hỗ trợ định dạng dữ liệu phổ biến như JSON, XML và các
định dạng tùy chỉnh khác. Bạn có thể chuyển đổi dữ liệu từ và thành các đối tượng Dart

sử dụng các gói hỗ trợ như dart:convert.

4. Xử lý lỗi: http.dart cung cấp các cơ chế để xử lý lỗi trong quá trình gửi yêu cầu và
nhận phản hồi từ REST API. Bạn có thể kiểm tra mã trạng thái của phản hồi để xác định
xem u cầu có thành cơng hay khơng và xử lý các tình huống lỗi một cách phù hợp.

5. Xác thực: Thư viện cung cấp cơ chế để xác thực với REST API bằng cách thêm tiêu đề
xác thực vào yêu cầu. Bạn có thể truyền các thơng tin xác thực như mã thông báo (token)
hoặc thông tin đăng nhập để xác thực với API.

Với http.dart, ta có thể tương tác với các REST API, gửi yêu cầu, nhận phản hồi và xử lý
dữ liệu trả về một cách dễ dàng. Thư viện này giúp ta xây dựng các ứng dụng Flutter kết
nối với dịch vụ web và tương tác với các tài nguyên từ REST API một cách linh hoạt và
tiện lợi.

Chương 3. XÂY DỰNG ỨNG DỤNG

3.1. Model
3.1.1 Hour_Forecast_model.dart

class Hourly_Model {
List<String>? hourlydt;
List<String>? hourlytemp;
List<String>? hourlyicon;

Hourly_Model({ required this.hourlydt,
required this.hourlytemp,
required this.hourlyicon});

Map<String, dynamic> toJson() {

return {
'hourlydt': this.hourlydt,
'hourlytemp': this.hourlytemp,
'hourlyicon': this.hourlyicon,
};

}
factory Hourly_Model.fromJson(dynamic json) {

return Hourly_Model(
hourlydt: [
json["list"][0]["dt"].toString(),
json["list"][1]["dt"].toString(),

lOMoARcPSD|11346942

json["list"][2]["dt"].toString(),
json["list"][3]["dt"].toString(),
json["list"][4]["dt"].toString(),
json["list"][5]["dt"].toString(),
json["list"][6]["dt"].toString(),
] as List<String>,

hourlytemp: [
json["list"][0]["main"]["temp"].toString(),
json["list"][1]["main"]["temp"].toString(),
json["list"][2]["main"]["temp"].toString(),
json["list"][3]["main"]["temp"].toString(),
json["list"][4]["main"]["temp"].toString(),
json["list"][5]["main"]["temp"].toString(),

json["list"][6]["main"]["temp"].toString()

] as List<String>,

hourlyicon: [
json["list"][0]["weather"][0]["icon"].toString(),
json["list"][1]["weather"][0]["icon"].toString(),
json["list"][2]["weather"][0]["icon"].toString(),
json["list"][3]["weather"][0]["icon"].toString(),
json["list"][4]["weather"][0]["icon"].toString(),
json["list"][5]["weather"][0]["icon"].toString(),
json["list"][6]["weather"][0]["icon"].toString(),

] as List<String>,

);
}
}

-Trong model ‘Hour_Forecast_model.dart’ chứa lớp Hourly_Model, mô tả thông tin về
dự báo thời tiết theo giờ. Lớp này có ba thuộc tính chính là hourlydt, hourlytemp, và
hourlyicon. Chúng lưu trữ các giá trị tương ứng về thời gian, nhiệt độ và biểu tượng thời
tiết cho từng khoảng thời gian trong ngày.

-Phương thức khởi tạo Hourly_Model được sử dụng để tạo ra một đối tượng mới của lớp
này. Nó nhận vào ba tham số bắt buộc hourlydt, hourlytemp, và hourlyicon, và gán chúng
cho các thuộc tính tương ứng của đối tượng.

-Phương thức toJson được sử dụng để chuyển đổi đối tượng Hourly_Model thành một đối
tượng Map. Đối tượng Map này sẽ chứa thông tin về thời gian, nhiệt độ và biểu tượng

thời tiết theo giờ. Khi gọi phương thức này, đối tượng Map được tạo và các thuộc tính
của đối tượng Hourly_Model sẽ được thêm vào đối tượng Map. Sau đó, đối tượng Map
sẽ được trả về.

Phương thức fromJson là một hàm tạo đặc biệt để tạo đối tượng Hourly_Model từ dữ liệu
JSON. Hàm này nhận một đối số là json, đại diện cho dữ liệu JSON chưa xác định kiểu
dữ liệu. Dựa trên cấu trúc của dữ liệu JSON, các giá trị tương ứng với thời gian, nhiệt độ

Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

và biểu tượng thời tiết được trích và gán cho các thuộc tính tương ứng của đối tượng
Hourly_Model. Cuối cùng, đối tượng Hourly_Model sẽ được tạo và trả về.

3.1.2. Weather_model.dart

class weatherModel {

final String? cityName;
final double temp;
final String? condition;
final double windspeed;
final int humidity;
final int pressure;
final double clouds;
final String? icon_id;

weatherModel({
required this.cityName,

required this.temp,
required this.condition,
required this.windspeed,
required this.humidity,
required this.pressure,
required this.clouds,
required this.icon_id,

});

Map<String, dynamic> toJson() {
return {
'cityName': this.cityName,
'temp': this.temp,
'condition': this.condition,
'windspeed': this.windspeed,
'humidity': this.humidity,
'pressure': this.pressure,
'clouds': this.clouds,
'icon_id': this.icon_id,
};

}

factory weatherModel.fromJson(dynamic json) {
return weatherModel(
cityName: json["name"].toString(),
temp: json["main"]["temp"].toDouble(),
condition: json["weather"][0]


["description"].toString().toUpperCase(),
windspeed: json["wind"]["speed"].toDouble(),
humidity: json["main"]["humidity"].toInt(),
pressure: json["main"]["pressure"].toInt(),
clouds: json["clouds"]["all"].toDouble(),
icon_id: json["weather"][0]["icon"].toString(),

);
}
}

Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

-Lớp weatherModel trong đoạn mã trên là một mơ hình dữ liệu để đại diện cho thông tin
về thời tiết của một thành phố cụ thể. Nó bao gồm các thuộc tính như cityName, temp,
condition, windspeed, humidity, pressure, clouds, và icon_id.

-Phương thức toJson được sử dụng để chuyển đổi đối tượng weatherModel thành một đối
tượng Map có kiểu dữ liệu gồm String là khóa và dynamic là giá trị. Trong phương thức
này, ta tạo ra một đối tượng Map mới và gán các thuộc tính của đối tượng weatherModel
cho các khóa tương ứng trong đối tượng Map. Kết quả là phương thức toJson trả về một
đối tượng Map chứa thông tin về các thuộc tính của đối tượng weatherModel.

-Phương thức fromJson được sử dụng để tạo một đối tượng weatherModel từ một đối
tượng dynamic có kiểu dữ liệu là JSON. Trong phương thức này, ta trích xuất thơng tin từ
JSON và gán cho các thuộc tính tương ứng của đối tượng weatherModel. Sau đó, ta tạo
và trả về một đối tượng weatherModel mới với các giá trị thuộc tính đã được gán.


3.2. Page
3.2.1. WeatherPage.dart

Widget build(BuildContext context) {
weatherData = Provider.of<WeatherProvider>(context).weatherData;
weatherData2 = Provider.of<WeatherProvider>(context).weatherData2;
return Scaffold(
body: Provider.of<WeatherProvider>(context).weatherData == null &&
Provider.of<WeatherProvider>(context).weatherData2 == null
? SearchPage()
: Container()

- Trong hàm build(), trước khi hiển thị giao diện thời tiết, trang chủ kiểm tra xem liệu dữ
liệu thời tiết có sẵn trong Provider hay khơng bằng cách kiểm tra xem các thuộc tính
weatherData và weatherData2 có khác null hay khơng.

Nếu khơng có dữ liệu thời tiết, trang chủ sẽ hiển thị trang tìm kiếm bằng cách gọi widget
SearchPage(). Nếu có dữ liệu thời tiết, trang chủ sẽ hiển thị giao diện thời tiết bằng cách
sử dụng một Container widget.

-Code giao diện hiển thị thời tiết:

Container(
child: SafeArea(
child: ListView(
children: <Widget>[
Container(
decoration: BoxDecoration(
image: DecorationImage(


Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

colorFilter: ColorFilter.mode(
Colors.black38, BlendMode.darken),

image: AssetImage(
'assets/cloud-in-blue-sky.jpg',

),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(25),
bottomRight: Radius.circular(25),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(

child: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(
Icons.menu,

color: Colors.white,
),
onPressed: () {},
),
actions: [
IconButton(
onPressed: () {
Navigator.push(context,
MaterialPageRoute(
builder: (context) {
return SearchPage(
updateUi: updateUi,
);
}));
},
icon: Icon(Icons.search)),
],

),
),
Padding(

padding: const EdgeInsets.only(top: 200.0),
child: Align(

alignment: Alignment(0.0, 1.0),
child: SizedBox(

height: 10,
width: 10,

child: OverflowBox(

maxWidth: MediaQuery.of(context).size.width,
maxHeight:

(MediaQuery.of(context).size.height /
3),

child: Stack(
children: <Widget>[
Container(
padding: EdgeInsets.symmetric(
horizontal: 20),
width: double.infinity,
height: double.infinity,
child: Card(
color: Colors.white,
elevation: 5,

Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

{weatherData!.condition}', shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(25),

),
child: Column(


crossAxisAlignment:
CrossAxisAlignment.center,

children: <Widget>[
//TODO
Container(
padding: EdgeInsets.only(
top: 15,
left: 20,
right: 20),
child: Column(
crossAxisAlignment:
CrossAxisAlignment
.start,
children: <Widget>[
Center(
child: Text(
'${weatherData!.cityName}'
.toUpperCase(),
style: TextStyle(
fontSize: 24,
color: Colors
.black45,
fontWeight:
FontWeight
.bold)),
),
Center(
child: Text(
DateFormat()

.add_MMMMEEEEd()
.format(DateTime
.now()),
style: TextStyle(
fontSize: 16,
color: Colors
.black45,
fontWeight:
FontWeight
.bold)),
),
],
),
),
Divider(),
//TODO
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.only(
left: 35),
child: Column(
children: <Widget>[
Text(
'$

style: TextStyle(


Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

color: Colors
.blueAccent,

fontSize: 30,
fontWeight:

FontWeight
.bold),

),
SizedBox(height: 10),
Text(

'$
{(weatherData!.temp.toString())}\u2103',

style: TextStyle(
fontSize: 16,
color: Colors
.black45,
fontWeight:
FontWeight
.bold),

),

],
),
),
Container(
padding: EdgeInsets.only(

right: 20),
child: Column(

mainAxisAlignment:
MainAxisAlignment
.center,

children: <Widget>[
SizedBox(
width: 120,
height: 120,
child: Image.asset(
"assets/weather/$

{weatherData!.icon_id}.png"),
),

],
),
),
],
),
Padding(
padding:

const EdgeInsets.only(

top: 10.0),
child: Column(

crossAxisAlignment:
CrossAxisAlignment
.start,

children: [
currentWeatherDetails(
weatherData!.windspeed
.toString(),
weatherData!.clouds
.toString(),
weatherData!.humidity
.toString()),

],
),
),
],
),
),

Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

),

],
),
),
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(top: 200.0, left: 20.0),
child: Align(
alignment: Alignment.topLeft,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: Text(
"Today".toUpperCase(),
style: TextStyle(
fontSize: 16,
color: Colors.black45,
fontWeight: FontWeight.bold),
),
),
SizedBox(
height: 170,
width: MediaQuery.of(context).size.width - 40,
child: ListView.builder(
scrollDirection: Axis.horizontal,

itemCount: 5,
itemBuilder: (BuildContext context, index) {
return HourlyWidget(

"${weatherData2!.hourlytemp?[index]}",
"${weatherData2!.hourlyicon?[index]}",
"${weatherData2?.hourlydt?[index]}",
index,
);
}),
),
SizedBox(
height: 30,
),
Container(
margin: const EdgeInsets.all(12),
height: 350,
padding: const EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.deepPurple[50],
borderRadius: BorderRadius.circular(20),
),
child: Column(
children: [
Text(
"Forecast for 7 days :",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w500,
letterSpacing: 0.5,

color: Colors.black,
),
),
const SizedBox(

Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

height: 30,
),
SizedBox(

height: 250,
width: 350,
child: ListView.builder(

itemCount: 5,
itemBuilder:

(BuildContext context, index) {
return DailyForcast(

"${weatherData2?.hourlydt![index]}",
"${weatherData2?.hourlyicon?[index]}",
"${weatherData2?.hourlytemp?[index]}",
);
}),
),
],

),
),
],
),
),
),
],
),
),
),

Trang chủ được chia thành hai phần chính. Nếu dữ liệu thời tiết chưa được cung cấp
(Provider.of<WeatherProvider>(context).weatherData==nullvàProvider.ofder>(context).weatherData2 == null), thì trang chủ sẽ hiển thị SearchPage để người dùng
có thể tìm kiếm thơng tin thời tiết cho một thành phố cụ thể.

Ngược lại, nếu dữ liệu thời tiết đã được cung cấp, trang chủ sẽ hiển thị một Container
chứa các thành phần hiển thị thông tin thời tiết.

Trong Container, có một SafeArea để đảm bảo hiển thị an tồn trên mọi thiết bị. Bên
trong SafeArea, có một ListView để chứa các thành phần con khác.

Các thành phần con bao gồm:

Phần tiêu đề và nút menu: Được hiển thị bên trên cùng của trang chủ. Nút menu khơng có
hành động cụ thể được xử lý trong mã này.

Phần hiển thị thông tin thời tiết hiện tại: Hiển thị tên thành phố, ngày hiện tại, điều kiện
thời tiết, nhiệt độ và biểu tượng thời tiết. Thông tin này được lấy từ weatherData thông
qua Provider.


Chi tiết thời tiết hiện tại: Hiển thị thơng tin về tốc độ gió, độ ẩm và độ che phủ mây.
Thông tin này được truyền vào hàm currentWeatherDetails và hiển thị trong một widget.

Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

Dự báo theo giờ: Hiển thị thông tin thời tiết dự báo theo giờ cho hôm nay. Mỗi mục được

hiển thị bằng một widget HourlyWidget, hiển thị nhiệt độ, biểu tượng và thời gian.

Dự báo trong 7 ngày: Hiển thị thông tin dự báo thời tiết cho 7 ngày tiếp theo. Mỗi mục

được hiển thị bằng một widget DailyForcast, hiển thị biểu tượng, nhiệt độ và ngày.

3.2.2. SearchPage.dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:weatherforecast/Models/Hour_Forecast_model.dart';

import '../Models/Weather_model.dart';
import '../Provider/WeatherProvider.dart';
import '../Services/Weather_API_Service.dart';

String? cityName ;

class SearchPage extends StatelessWidget {
SearchPage({this.updateUi});


VoidCallback? updateUi;

@override
Widget build(BuildContext context) {

return Scaffold(
appBar: AppBar(
title: Text("Search a City"),
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Center(
child: SizedBox(
width: 300.0,
height: 100.0,
child: Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Column(
children: <Widget>[
TextField(
style: TextStyle(
fontSize: 20,
),
onSubmitted: (data) async {
cityName = data;
WeatherService Service = WeatherService();
weatherModel weather1 =

await Service.getWeather(CityName: cityName!);
Hourly_Model weather2 =
(await Service.getHourlyWeather(CityName:

cityName!)) as Hourly_Model;
Provider.of<WeatherProvider>(context, listen:

false)
.weatherData = weather1;

Provider.of<WeatherProvider>(context, listen:
false)

.weatherData2 = weather2;
Navigator.of(context).maybePop() ;

Downloaded by Quang Tr?n ()

lOMoARcPSD|11346942

},
decoration: InputDecoration(

contentPadding: EdgeInsets.symmetric(
vertical: 10, horizontal: 20),

suffixIcon: GestureDetector(
onTap: () async {
WeatherService Service = WeatherService();
weatherModel weather1 =

await Service.getWeather(CityName:

cityName!);
Hourly_Model weather2 =
(await Service.getHourlyWeather(CityName:

cityName!)) as Hourly_Model;
Provider.of<WeatherProvider>(context, listen:

false)
.weatherData = weather1;

Provider.of<WeatherProvider>(context, listen:
false)

.weatherData2 = weather2;
Navigator.of(context).maybePop() ;
},
child: Icon(Icons.search)),
hintText: "Nhập đ椃⌀a điऀm",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30.0),
),
),
)
],
),
),
),
),

],
),
),
);
}
}

-Các đối số của SearchPage là updateUi, một VoidCallback được sử dụng để cập nhật

giao diện người dùng.

Trong build method, được định nghĩa một Scaffold để tạo ra một trang có tiêu đề "Search

a City". Phần thân (body) của Scaffold bao gồm một SafeArea chứa một cột (Column)

chính.

Trong cột chính, có một Center widget để căn giữa các thành phần bên trong. Bên trong

Center, có một SizedBox với chiều rộng 300.0 và chiều cao 100.0 để giới hạn kích thước

của thành phần.

Bên trong SizedBox, có một Padding để thêm khoảng cách phía trên cho thành phần.

Trong Padding, có một Column để chứa các thành phần con khác.

Downloaded by Quang Tr?n ()



×