조금매운맛 15 날씨 앱 만들기 3 : Passing json data(json 데이터 전달하기)
위도, 경두 따로 출력을 위해 변수 선언해서 출력
class _LoadingState extends State<Loading> {
double? latitude2; // 위도
double? longitude2; // 경도
@override
void initState() {
// TODO: implement initState
super.initState();
getLocation();
fetchData();
}
void fetchData() async {
http.Response response = await http.get(Uri.parse(
'https://samples.openweathermap.org/data/2.5/weather?q=London&appid=b1b15e88fa797225412429c1c50c122a1'));
if(response.statusCode ==200){
String jsonData = response.body;
var myJson = jsonDecode(jsonData)['weather'][0]['description'];
var myWind = jsonDecode(jsonData)['wind']['speed'];
var myId = jsonDecode(jsonData)['id'];
print(myJson);
print(myWind);
print(myId);
}else{
print(response.statusCode);
}
}
//현재 위치 정보 얻기
void getLocation() async{
try{
LocationPermission permission = await Geolocator.requestPermission();
Position position = await Geolocator.
getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
latitude2 = position.latitude;
longitude2 = position.longitude;
print(latitude2); //추가
print(longitude2); //추가
}catch(e){
print('There was a problem with the internet connection.');
}
}
효율을 위해서 냅다 다 같이 넣어 만들었던 코드를 <리팩토링>
해당 위치에 폴더를 만들어서 my_location.dart 생성
다음처럼 수정
//my_location.dart
import 'package:geolocator/geolocator.dart';
class MyLocation{
double? latitude2; // 위도
double? longitude2; // 경도
Future<void> getMyCurrentLocation() async{
try{
LocationPermission permission = await Geolocator.requestPermission();
Position position = await Geolocator.
getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
latitude2 = position.latitude;
longitude2 = position.longitude;
print(latitude2); //추가
print(longitude2); //추가
}catch(e){
print('There was a problem with the internet connection.');
}
}
}
//loading.dart
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter_weather/data/my_location.dart';
class Loading extends StatefulWidget {
const Loading({Key? key}) : super(key: key);
@override
State<Loading> createState() => _LoadingState();
}
class _LoadingState extends State<Loading> {
double? latitude2; // 위도
double? longitude2; // 경도
@override
void initState() {
// TODO: implement initState
super.initState();
getLocation();
fetchData();
}
void fetchData() async {
http.Response response = await http.get(Uri.parse(
'https://samples.openweathermap.org/data/2.5/weather?q=London&appid=b1b15e88fa797225412429c1c50c122a1'));
if(response.statusCode ==200){
String jsonData = response.body;
var myJson = jsonDecode(jsonData)['weather'][0]['description'];
var myWind = jsonDecode(jsonData)['wind']['speed'];
var myId = jsonDecode(jsonData)['id'];
print(myJson);
print(myWind);
print(myId);
}else{
print(response.statusCode);
}
}
void getLocation() async{
MyLocation myLocation = MyLocation();
await myLocation.getMyCurrentLocation();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: (){
null;
},
child: Text('get my location'),
),
),
);
}
}
실행 과정 다시 되짚기
1. 앱 실행 시 MyApp 위젯 호출
2. MyApp 위젯은 Loading 위젯 호출
3. Loading 위젯 호출되어 생성되는 순간 initState 메소드 실행되면서 getLocation 메소드 호출
4. getLocation 메소드 호출될때, MyLocation을 통해서 MyLocation 인스턴스를 생성
5. MyLocation내의 getMyCurrentLocation 메소드 불러옴
6. getMyCurrentLocation 메소드 불러올때. getMyCurrentLocation 메소드 내에서는 geolocator 패키지 사용해서 위도,경도를 position 변수에 전달하고 이를 위해서 await 키워드를 이용해 asynd방식으로 동작
7. getLocation 메소드 내에서도 getMyCurrentLocation 메소드를 통해서 위도, 경도가 position 변수에 할당될때까지 기다리기위해 await 키워드를 통해서 async 방식으로 작동함
8. await 키워드는 future값을 기다리므로 getMyCurrentLocation 메소드는 Future<void> 타입으로 지정되어 있어야함
class _LoadingState extends State<Loading> {
double? latitude3;
double? longitude3;
void getLocation() async{
MyLocation myLocation = MyLocation();
await myLocation.getMyCurrentLocation();
latitude3 = myLocation.latitude2;
longitude3 = myLocation.longitude2;
print(latitude3);
print(longitude3);
}
}
> myLocation에서 받은 위도경도값이 잘 받아서 출력되는지 확인
//loading.dart
import 'package:flutter/material.dart';
import 'package:flutter_weather/data/my_location.dart';
import 'package:flutter_weather/data/network.dart';
class Loading extends StatefulWidget {
const Loading({Key? key}) : super(key: key);
@override
State<Loading> createState() => _LoadingState();
}
class _LoadingState extends State<Loading> {
double? latitude3;
double? longitude3;
@override
void initState() {
// TODO: implement initState
super.initState();
getLocation();
}
// void fetchData() async {
//
// var myJson = parsingData['weather'][0]['description'];
// var myWind = parsingData['wind']['speed'];
// var myId = parsingData['id'];
//
// print(myJson);
// print(myWind);
// print(myId);
// }else{
// print(response.statusCode);
// }
// }
void getLocation() async{
MyLocation myLocation = MyLocation();
await myLocation.getMyCurrentLocation();
latitude3 = myLocation.latitude2;
longitude3 = myLocation.longitude2;
print(latitude3);
print(longitude3);
Network network = Network('https://api.openweathermap.org/data/2.5/'
'weather?q=London&appid=b1b15e88fa797225412429c1c50c122a1');
var weatherData = await network.getJsonData();
print(weatherData);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: (){
null;
},
child: Text('get my location'),
),
),
);
}
}
//network.dart
import 'package:http/http.dart' as http;
import 'dart:convert';
class Network{
final String url;
Network(this.url);
Future<dynamic> getJsonData() async {
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
String jsonData = response.body;
var parsingData = jsonDecode(jsonData);
return parsingData;
}
}
}
결과로 잘 출력됨
이제 실시간 날씨 데이터 얻어오기
//loading.dart
Network network = Network('https://api.openweathermap.org/data/3.0/'
'onecall?lat={lat}&lon={lon}&exclude={part}&appid={API key}');
> 더미데이터 대신 api 집어넣기
const apikey = 'd4ce3534d부여받은 키값9fbfe946';
> openweather 사이트에 로그인 해서 할당받은 키값을 loading.dart 상단에 추가
> const 키워드는 apikey은 더이상 변하지 않을 거기 때문에 붙여줌
Network network = Network('https://api.openweathermap.org/data/3.0/'
'onecall?lat=$latitude3&lon=$longitude3&exclude={part}&appid=$apikey');
> $위도, $경도, $api키 넣어주기
* 결과는 실패. null이 나옴
API 키가 활성화 안되서 강사님 키 넣으니까 잘됨
◼ 로딩페이지에서 날씨데이터가 모두 생성되면 날씨스크린으로 이동하게 만듦
해당 위치에 weather_screen.dart 파일 생성
//weather_screen.dart
import 'package:flutter/material.dart';
class WeatherScreen extends StatefulWidget {
@override
State<WeatherScreen> createState() => _WeatherScreenState();
}
class _WeatherScreenState extends State<WeatherScreen> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
getLocation 메소드에 추가
Navigator.push(context, MaterialPageRoute(builder: (context){
return WeatherScreen();
}));
//weather_screen.dart
import 'package:flutter/material.dart';
class WeatherScreen extends StatefulWidget {
WeatherScreen({this.parseWeatherData});
final parseWeatherData; //받을 데이터들의 타입을 dynamic 타입으로 지정하기 위해서 따로 타입 지정 ㄴㄴ
@override
State<WeatherScreen> createState() => _WeatherScreenState();
}
class _WeatherScreenState extends State<WeatherScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'City name',
style: TextStyle(fontSize: 30.0),
),
SizedBox(
height: 20.0,
),
Text(
'Temperature',
style: TextStyle(fontSize: 30.0),
)
],
),
),
),
);
}
}
네비게이터도 수정
Navigator.push(context, MaterialPageRoute(builder: (context){
return WeatherScreen(parseWeatherData: weatherData,);
weatherScreen 속성인 parseWeatherData를 어떻게 _WeatherScreenState 객체로 전달할 수 있을까?
> 앱 스크린 상에서 눈으로 확인 할 수 있도록 날씨데이터를 출력해주는 text 위젯은 weatherScreen 클래스가 아니라 weatherScreen state 클래스의 build 메소드 내에 포함되어 있음.
> 그래서 매번 날씨앱을 켤때마다 loading 위젯으로부터 업데이트된 데이터가 parseWeatherData로 전달됨
> 그때마다 weatherScreen state 내에 있는 text 위젯에 변화를 반영
Stateful Widget은 2개 클래스의 결합으로 이루어져 있음
State 클래스는 제네릭스 기법을 사용해서 Stateful인 특정 부모클래스를 지정해 바인드 될수 있음
State 클래스는 widget 속성을 갖는다.
이때 widget은 현재의 구성, 즉 현재의 Stateful widget Instance와 같음.
= 이 속성을 사용해서 state 객체가 parent 객체인 WeatherScreen Stateful widget이 가지고 있는 모든 데이터에 접근할 수 있다
//weather_screen.dart
class _WeatherScreenState extends State<WeatherScreen> {
@override
void initState() {
// TODO: implement initState
super.initState();
print(widget.parseWeatherData);
}
void updateData(dynamic weatherData){
temp = weatherData['main']['temp'];
cityName = weatherData['name'];
print(temp);
print(cityName);
}
> 데이터 출력 잘 됨
> 나는 안됨
* 이전까진 괜찮다가 weatherScreen 파일 initState에서 widget.parseWeatherData를 프린트할때 Null값이 뜨고 화면은 에러가 뜬다.
한국 자료가 별로 없어서 스택오버플로우도 보고 난리생쇼를 부리다가 api 주소가 잘못 됬다는걸 찾았다.
주소가 잘못되서 계속 null값이 들어갔고 그러니 당연히 에러가 이어졌음. ㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎ
Network network = Network(
"https://api.openweathermap.org/data/2.5/weather?lat=$latitude3&lon=$longitude3&appid=$apikey&units=metric");
◼ 넘어온 데이터들을 앱화면에 출력
Text(
'$cityName',
style: TextStyle(fontSize: 30.0),
),
SizedBox(
height: 20.0,
),
Text(
'$temp',
style: TextStyle(fontSize: 30.0),
)
],
결과
조금매운맛 15 전체코드 (main.dart 제외)
//weather 어쩌구 .dart
import 'package:flutter/material.dart';
class WeatherScreen extends StatefulWidget {
WeatherScreen({this.parseWeatherData}); //생성자
final dynamic parseWeatherData; //받을 데이터들의 타입을 dynamic 타입으로 지정하기 위해서 따로 타입 지정 ㄴㄴ
@override
State<WeatherScreen> createState() => _WeatherScreenState();
}
class _WeatherScreenState extends State<WeatherScreen> {
String? cityName;
int? temp;
@override
void initState() {
// TODO: implement initState
super.initState();
updateData(widget.parseWeatherData); //문제구간
}
void updateData(dynamic weatherData){
double temp2 = weatherData['main']['temp']; //문제구간
temp = temp2.round();
cityName = weatherData['name'];
print(temp);
print(cityName);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$cityName',
style: TextStyle(fontSize: 30.0),
),
SizedBox(
height: 20.0,
),
Text(
'$temp',
style: TextStyle(fontSize: 30.0),
)
],
),
),
),
);
}
}
//loading.dart
import 'package:flutter/material.dart';
import 'package:flutter_weather/data/my_location.dart';
import 'package:flutter_weather/data/network.dart';
import 'package:flutter_weather/screens/weather_screen.dart';
const apikey = 'd4ce3534deb8eb1a4a2df7759fbfe946';
class Loading extends StatefulWidget {
@override
State<Loading> createState() => _LoadingState();
}
class _LoadingState extends State<Loading> {
double? latitude3;
double? longitude3;
@override
void initState() {
// TODO: implement initState
super.initState();
getLocation();
}
void getLocation() async {
MyLocation myLocation = MyLocation();
await myLocation.getMyCurrentLocation();
latitude3 = myLocation.latitude2;
longitude3 = myLocation.longitude2;
print(latitude3);
print(longitude3);
Network network = Network(
"https://api.openweathermap.org/data/2.5/weather?lat=$latitude3&lon=$longitude3&appid=$apikey&units=metric");
var weatherData = await network.getJsonData();
print(weatherData);
Navigator.push(context, MaterialPageRoute(builder: (context) {
return WeatherScreen(
parseWeatherData: weatherData,
);
}));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: (){},
child: Text('get my location'),
),
),
);
}
}
//network.dart
import 'package:http/http.dart' as http;
import 'dart:convert';
class Network{
final String url;
Network(this.url);
Future<dynamic> getJsonData() async {
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
String jsonData = response.body;
var parsingData = jsonDecode(jsonData);
return parsingData;
}
}
}
//my_location.dart
import 'package:geolocator/geolocator.dart';
class MyLocation{
double? latitude2;
double? longitude2;
Future<void> getMyCurrentLocation() async{
try{
LocationPermission permission = await Geolocator.requestPermission();
Position position = await Geolocator.
getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
latitude2 = position.latitude;
longitude2 = position.longitude;
}catch(e){
print('There was a problem with the internet connection.');
}
}
}
조금매운맛 16 날씨 앱 만들기 4 : UI 디자인 (null safety 적용버전)
구글폰트
google_fonts: ^4.0.2
flutter_svg
flutter_svg: ^2.0.1
> sdk 버전이 어쩌구저쩌구 에러 뜨는데 터미널에서 flutter uprade 하고 pub get/upgrade 하면 어찌어찌 해결...
...인줄 알았으나 개발자모드 에러가 또 발생
Building with plugins requires symlink support. Please enable Developer Mode in your system settings. Run start ms-settings:developers to open settings.
블로그를 통해서 개발자모드 활성화해주면 해결
https://github.com/icodingchef/lecture
위 깃허브 통해서 image와 svg 다운
timer_builder : 현재시간 불러옴
timer_builder: ^2.0.0
init : 현재시간을 우리가 정한 형식에 맞춰서 출력하기 위한
intl: ^0.18.0
전부 임포트해주기
//weather_screen.dart
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:timer_builder/timer_builder.dart';
import 'package:intl/intl.dart';
전체 날씨어플의 완성본 및 UI 구조
UI 전체 코드
//weather_screen.dart
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:timer_builder/timer_builder.dart';
import 'package:intl/intl.dart';
class WeatherScreen extends StatefulWidget {
WeatherScreen({this.parseWeatherData}); //생성자
final dynamic parseWeatherData; //받을 데이터들의 타입을 dynamic 타입으로 지정하기 위해서 따로 타입 지정 ㄴㄴ
@override
State<WeatherScreen> createState() => _WeatherScreenState();
}
class _WeatherScreenState extends State<WeatherScreen> {
String? cityName;
int? temp;
var date = DateTime.now();
@override
void initState() {
// TODO: implement initState
super.initState();
updateData(widget.parseWeatherData); //문제구간
}
void updateData(dynamic weatherData){
double temp2 = weatherData['main']['temp']; //문제구간
temp = temp2.round();
cityName = weatherData['name'];
print(temp);
print(cityName);
}
String getSystemTime() {
var now = DateTime.now();
return DateFormat('h:mm a').format(now);
}
@override
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true, //appbar 숨기기
appBar: AppBar(
title: Text(''),
backgroundColor: Colors.transparent, //appbar 숨기기
elevation: 0, //appbar 숨기기
leading: IconButton(
icon: Icon(Icons.near_me),
onPressed: () {},
iconSize: 30.0,
),
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.location_searching),
iconSize: 30.0,
)
],
),
body: Container(
child: Stack(
children: [
Image.asset(
'images/background.jpg',
fit: BoxFit.cover,
height: double.infinity,
),
Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 150,
),
Text(
'Seoul',
style: GoogleFonts.lato(
fontSize: 30.0,
fontWeight: FontWeight.bold,
color: Colors.white),
),
Row(
children: [
TimerBuilder.periodic(
(Duration(minutes: 1)),
builder: (context) {
print(getSystemTime());
return Text(
getSystemTime(),
style: GoogleFonts.lato(
fontSize: 10.0, color: Colors.white),
);
},
),
Text(
DateFormat('- EEEE').format(date),
style: GoogleFonts.lato(
fontSize: 10.0, color: Colors.white),
),
Text(DateFormat('d MMM, yyy').format(date),
style: GoogleFonts.lato(
fontSize: 10, color: Colors.white))
],
)
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'18\u2103',
style: GoogleFonts.lato(
fontSize: 30.0,
fontWeight: FontWeight.w300,
color: Colors.white),
),
Row(
children: [
SvgPicture.asset('svg/climacon-sun.svg'),
Text(
'Clear Sky',
style: GoogleFonts.lato(
fontSize: 10, color: Colors.white),
)
],
)
],
)
],
),
),
Column(
children: [
Divider(
height: 15,
thickness: 2,
color: Colors.white30,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
Text(
'AQI(대기질지수)',
style: GoogleFonts.lato(
fontSize: 8, color: Colors.white),
),
SizedBox(
height: 10,
),
Image.asset(
'images/bad.png',
width: 26,
height: 25,
),
SizedBox(
height: 10.0,
),
Text(
'"매우나쁨"',
style: GoogleFonts.lato(
fontSize: 8,
color: Colors.black87,
fontWeight: FontWeight.bold),
)
],
),
Column(
children: [
Text(
'미세먼지',
style: GoogleFonts.lato(
fontSize: 8, color: Colors.white),
),
SizedBox(
height: 10,
),
Text(
'173.53',
style: GoogleFonts.lato(
fontSize: 15, color: Colors.white),
),
SizedBox(
height: 10.0,
),
Text(
'ug/m3',
style: GoogleFonts.lato(
fontSize: 8,
color: Colors.black87,
fontWeight: FontWeight.bold),
)
],
),
Column(
children: [
Text(
'초미세먼지',
style: GoogleFonts.lato(
fontSize: 8.0,
color: Colors.white,
),
),
SizedBox(
height: 10.0,
),
Text(
'85.4',
style: GoogleFonts.lato(
fontSize: 15.0,
color: Colors.white,
),
),
SizedBox(
height: 8.0,
),
Text(
'㎍/m3',
style: GoogleFonts.lato(
fontSize: 8.0,
color: Colors.white,
fontWeight: FontWeight.bold),
)
],
)
],
)
],
)
],
),
)
],
),
),
);
}
}
조금 매운맛 17 날씨 앱 만들기 5 : 날씨 앱 UI 데이터 연동하기
미세먼지 데이터도 포함해서 표시 https://openweathermap.org/api/air-pollution#fields
결과물
> 위 결과물과 같이 이미지들이 null safety로 인해서 불러와지지 않는 현상이 있다.
나름 댓글과 구글링을 해결해보려고 했지만 쉽지 않아서 조금 매운맛 19강 포함해서 마이그레이션 한 것까지 포함 코드를 를 올리고자 한다.
조금매운맛 19 날씨 앱 만들기 6. : 날씨 앱 Null safety Migration
loadingindicator
https://pub.dev/packages/flutter_spinkit
flutter_spinkit: ^5.1.0
//loading.dart
import 'package:flutter_spinkit/flutter_spinkit.dart';
로딩애니메이션 추가
//loading.dart
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
body: Center(
child: SpinKitDoubleBounce(
color: Colors.white,
size: 80.0,
),
),
);
}
전체코드
// main.dart
import 'package:flutter/material.dart';
import 'screens/loading.dart';
void main(){
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Weather app',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Loading(),
);
}
}
//screens/weather_screen.dart
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:timer_builder/timer_builder.dart';
import 'package:intl/intl.dart';
import 'package:flutter_weather/model/model.dart';
class WeatherScreen extends StatefulWidget {
WeatherScreen({this.parseWeatherData, this.parseAirPollution}); //생성자
final dynamic parseWeatherData; //받을 데이터들의 타입을 dynamic 타입으로 지정하기 위해서 따로 타입 지정 ㄴㄴ
final dynamic parseAirPollution;
@override
State<WeatherScreen> createState() => _WeatherScreenState();
}
class _WeatherScreenState extends State<WeatherScreen> {
Model model = Model();
String? cityName;
int? temp;
String? des;
Widget? icon;
Widget? pollution;
Widget? quality;
double? air;
double? air2;
var date = DateTime.now();
@override
void initState() {
// TODO: implement initState
super.initState();
updateData(widget.parseWeatherData, widget.parseAirPollution);
}
void updateData(dynamic weatherData, dynamic airData){
double temp2 = weatherData['main']['temp'].toDouble();
temp = temp2.toInt();
cityName = weatherData['name'];
var condition = weatherData['weather'][0]['id'];
var grade = airData['list'][0]['main']['aqi'];
var index = airData['list'][0]['main']['aqi'];
des = weatherData['weather'][0]['description'];
icon = model.getWeatherIcon(condition);
pollution = model.getAirIcon(grade);
quality = model.airIndex(index);
air = airData['list'][0]['components']['pm2_5'];
air2 = airData['list'][0]['components']['pm10'];
print(temp);
print(cityName);
print(temp);
print(cityName);
}
String getSystemTime() {
var now = DateTime.now();
return DateFormat('h:mm a').format(now);
}
@override
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true, //appbar 숨기기
appBar: AppBar(
title: Text(''),
backgroundColor: Colors.transparent, //appbar 숨기기
elevation: 0, //appbar 숨기기
leading: IconButton(
icon: Icon(Icons.near_me),
onPressed: () {},
iconSize: 30.0,
),
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.location_searching),
iconSize: 30.0,
)
],
),
body: Container(
child: Stack(
children: [
Image.asset(
'images/background.jpg',
fit: BoxFit.cover,
height: double.infinity,
),
Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
height: 150,
),
Text(
'$cityName',
style: GoogleFonts.lato(
fontSize: 50.0,
fontWeight: FontWeight.bold,
color: Colors.white),
),
Row(
children: [
TimerBuilder.periodic(
(Duration(minutes: 1)),
builder: (context) {
print("${getSystemTime()}");
return Text(
"${getSystemTime()}",
style: GoogleFonts.lato(
fontSize: 20.0, color: Colors.white),
);
},
),
Text(
DateFormat('- EEEE').format(date),
style: GoogleFonts.lato(
fontSize: 20.0, color: Colors.white),
),
Text(DateFormat('d MMM, yyy').format(date),
style: GoogleFonts.lato(
fontSize: 20.0, color: Colors.white))
],
)
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'$temp\u2103',
style: GoogleFonts.lato(
fontSize: 85.0,
fontWeight: FontWeight.w300,
color: Colors.white),
),
Row(
children: [
icon!,
SizedBox(
width: 10,
),
Text(
'$des',
style: GoogleFonts.lato(
fontSize: 20.0,
//fontWeight: FontWeight.bold,
color: Colors.white),
),
],
)
],
)
],
),
),
Column(
children: [
Divider(
height: 15,
thickness: 2,
color: Colors.white30,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
Text(
'AQI(대기질지수)',
style: GoogleFonts.lato(
fontSize: 15, color: Colors.white),
),
SizedBox(
height: 10,
),
pollution!,
SizedBox(
height: 10.0,
),
quality!,
],
),
Column(
children: [
Text(
'미세먼지',
style: GoogleFonts.lato(
fontSize: 15, color: Colors.white),
),
SizedBox(
height: 10,
),
Text(
'$air2',
style: GoogleFonts.lato(
fontSize: 15, color: Colors.white),
),
SizedBox(
height: 10.0,
),
Text(
'ug/m3',
style: GoogleFonts.lato(
fontSize: 10,
color: Colors.black87,
fontWeight: FontWeight.bold),
)
],
),
Column(
children: [
Text(
'초미세먼지',
style: GoogleFonts.lato(
fontSize: 15.0,
color: Colors.white,
),
),
SizedBox(
height: 10.0,
),
Text(
'$air',
style: GoogleFonts.lato(
fontSize: 15.0,
color: Colors.white,
),
),
SizedBox(
height: 8.0,
),
Text(
'㎍/m3',
style: GoogleFonts.lato(
fontSize: 10.0,
color: Colors.white,
fontWeight: FontWeight.bold),
)
],
)
],
)
],
)
],
),
)
],
),
),
);
}
}
//model.dart
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
class Model {
Widget? getWeatherIcon(int condition) {
if (condition < 300) {
return SvgPicture.asset('svg/climacon-cloud_lightning.svg',
color: Colors.black87);
} else if (condition < 600) {
return SvgPicture.asset('svg/climacon-cloud_snow_alt.svg',
color: Colors.black87);
} else if (condition == 800) {
return SvgPicture.asset('svg/climacon-sun.svg',
color: Colors.black87);
} else if (condition <= 804) {
return SvgPicture.asset('svg/climacon-cloud_sun.svg',
color: Colors.black87);
}
return SvgPicture.asset('svg/climacon-sun.svg');
}
Widget? getAirIcon(int? index) {
if (index == 1) {
return Image.asset(
'images/good.png',
width: 20.0,
height: 19.0,
);
} else if (index == 2) {
return Image.asset(
'images/fair.png',
width: 20.0,
height: 19.0,
);
} else if (index == 3) {
return Image.asset(
'images/moderate.png',
width: 20.0,
height: 19.0,
);
} else if (index == 4) {
return Image.asset(
'images/poor.png',
width: 20.0,
height: 19.0,
);
} else if (index == 5) {
return Image.asset(
'images/bad.png',
width: 20.0,
height: 19.0,
);
}
return Image.asset(
'images/good.png',
width: 20.0,
height: 19.0,
);
}
Widget? airIndex(int index) {
if (index == 1) {
return Text(
'"매우좋음"',
style: TextStyle(
color: Colors.indigo,
fontWeight: FontWeight.bold,
),
);
} else if (index == 2) {
return Text(
'"좋음"',
style: TextStyle(
color: Colors.indigo,
fontWeight: FontWeight.bold,
),
);
} else if (index == 3) {
return Text(
'"보통"',
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
),
);
} else if (index == 4) {
return Text(
'"나쁨"',
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
),
);
} else if (index == 5) {
return Text(
'"매우나쁨"',
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
),
);
}
return Text(
'"몰라유"',
style: TextStyle(
color: Colors.black87,
fontWeight: FontWeight.bold,
),
);
}
}
//network.dart
import 'package:http/http.dart' as http;
import 'dart:convert';
class Network{
final String url;
final String url2;
Network(this.url, this.url2);
Future<dynamic> getJsonData() async {
http.Response response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
String jsonData = response.body;
var parsingData = jsonDecode(jsonData);
return parsingData;
}
}
Future<dynamic> getAirData() async {
http.Response response = await http.get(Uri.parse(url2));
if (response.statusCode == 200) {
String jsonData = response.body;
var parsingData = jsonDecode(jsonData);
return parsingData;
}
}
}
//lodaing.dart
import 'package:flutter/material.dart';
import 'package:flutter_weather/data/my_location.dart';
import 'package:flutter_weather/data/network.dart';
import 'package:flutter_weather/screens/weather_screen.dart';
const apikey = 'd4ce3534deb8eb1a4a2df7759fbfe946';
class Loading extends StatefulWidget {
@override
State<Loading> createState() => _LoadingState();
}
class _LoadingState extends State<Loading> {
double? latitude3;
double? longitude3;
@override
void initState() {
// TODO: implement initState
super.initState();
getLocation();
}
void getLocation() async {
MyLocation myLocation = MyLocation();
await myLocation.getMyCurrentLocation();
latitude3 = myLocation.latitude2;
longitude3 = myLocation.longitude2;
print(latitude3);
print(longitude3);
Network network = Network(
"https://api.openweathermap.org/data/2.5/weather?lat=$latitude3&lon=$longitude3&appid=$apikey&units=metric",
'https://api.openweathermap.org/data/2.5/air_pollution?lat=$latitude3&lon=$longitude3&appid=$apikey');
var weatherData = await network.getJsonData();
print(weatherData);
var airData = await network.getAirData();
print(airData);
Navigator.push(context, MaterialPageRoute(builder: (context) {
return WeatherScreen(
parseWeatherData: weatherData,
parseAirPollution: airData,
);
}));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: (){},
child: Text('get my location'),
),
),
);
}
}
'공부 > Flutter' 카테고리의 다른 글
Flutter 스터디 24 Flutter Key 이해하기(Value Key, Global Key) (0) | 2023.02.20 |
---|---|
Flutter 오류 Entrypoint isn't within the current project (0) | 2023.02.16 |
Flutter 스터디 22 날씨 앱 만들기 (widget lifecycle, API, Exception handling, Http pacage, Json parsing) (0) | 2023.02.16 |
Flutter 스터디 21 Flutter 2.0과 Null safety 널 세이프티 (0) | 2023.02.13 |
Flutter 스터디 20 반복문 loop와 추첨 프로그램, Future-async 심화학습 (1) | 2023.02.13 |