이번에는 데이터 모델을 만드는 방법에 대해서 알아보겠습니다.
개발환경 : 윈도우11, 안드로이드 스튜디오(Arctic Fox 2020.3.1 Patch 4), flutter 2.8.1
소스코드 위치 - Release data_model · mike-bskim/weather · GitHub
데이터 모델을 쉽게 만드는 툴/웹/플러그인들이 있는데, 그중에서 안드로이드 스튜디오에서 추가 가능한 "JsonToDart" 라는 플러그인으로 변환작업을 하였습니다.
model 폴더를 만들고 우클릭으로 "Json To Dart" 를 실행한다. 이전 블로그에서 사용한 샘플 데이터를 복/붙한다.
주의 사항))) 복/붙할때 주의 사항은 키/값중에 값에 공백이 있는 경우는 반드시 따옴표로 묶어주어야 한다. 복/붙 후, 오른쪽 상단의 "Format" 버튼을 클릭해서 형식이 보기좋게 변하지 않으면 공백이 포함된 값이 있는경우이니 주의하자.
생성된 model/current_weather.dart 파일 파일이 길어서 "더보기" 처리했습니다.
내용을 모두 보려면 "더보기" 클릭하세요.
더보기
/// coord : {"lon":9.19,"lat":45.4642}
/// weather : [{"id":802,"main":"Clouds","description":"구름조금","icon":"03d"}]
/// base : "stations"
/// main : {"temp":18.73,"feels_like":17.94,"temp_min":17.67,"temp_max":20.4,"pressure":1023,"humidity":49}
/// visibility : 10000
/// wind : {"speed":3.09,"deg":90}
/// clouds : {"all":40}
/// dt : 1651140421
/// sys : {"type":2,"id":2012644,"country":"IT","sunrise":1651119376,"sunset":1651170299}
/// timezone : 7200
/// id : 3173435
/// name : "Milan"
/// cod : 200
class CurrentWeather {
Coord? _coord;
List<Weather>? _weather;
String? _base;
Main? _main;
int? _visibility;
Wind? _wind;
Clouds? _clouds;
int? _dt;
Sys? _sys;
int? _timezone;
int? _id;
String? _name;
int? _cod;
CurrentWeather({
Coord? coord,
List<Weather>? weather,
String? base,
Main? main,
int? visibility,
Wind? wind,
Clouds? clouds,
int? dt,
Sys? sys,
int? timezone,
int? id,
String? name,
int? cod,
}) {
_coord = coord;
_weather = weather;
_base = base;
_main = main;
_visibility = visibility;
_wind = wind;
_clouds = clouds;
_dt = dt;
_sys = sys;
_timezone = timezone;
_id = id;
_name = name;
_cod = cod;
}
CurrentWeather.fromJson(dynamic json) {
_coord = json['coord'] != null ? Coord.fromJson(json['coord']) : null;
if (json['weather'] != null) {
_weather = [];
json['weather'].forEach((v) {
_weather?.add(Weather.fromJson(v));
});
}
_base = json['base'];
_main = json['main'] != null ? Main.fromJson(json['main']) : null;
_visibility = json['visibility'];
_wind = json['wind'] != null ? Wind.fromJson(json['wind']) : null;
_clouds = json['clouds'] != null ? Clouds.fromJson(json['clouds']) : null;
_dt = json['dt'];
_sys = json['sys'] != null ? Sys.fromJson(json['sys']) : null;
_timezone = json['timezone'];
_id = json['id'];
_name = json['name'];
_cod = json['cod'];
}
Coord? get coord => _coord;
List<Weather>? get weather => _weather;
String? get base => _base;
Main? get main => _main;
int? get visibility => _visibility;
Wind? get wind => _wind;
Clouds? get clouds => _clouds;
int? get dt => _dt;
Sys? get sys => _sys;
int? get timezone => _timezone;
int? get id => _id;
String? get name => _name;
int? get cod => _cod;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
if (_coord != null) {
map['coord'] = _coord?.toJson();
}
if (_weather != null) {
map['weather'] = _weather?.map((v) => v.toJson()).toList();
}
map['base'] = _base;
if (_main != null) {
map['main'] = _main?.toJson();
}
map['visibility'] = _visibility;
if (_wind != null) {
map['wind'] = _wind?.toJson();
}
if (_clouds != null) {
map['clouds'] = _clouds?.toJson();
}
map['dt'] = _dt;
if (_sys != null) {
map['sys'] = _sys?.toJson();
}
map['timezone'] = _timezone;
map['id'] = _id;
map['name'] = _name;
map['cod'] = _cod;
return map;
}
}
/// type : 2
/// id : 2012644
/// country : "IT"
/// sunrise : 1651119376
/// sunset : 1651170299
class Sys {
int? _type;
int? _id;
String? _country;
int? _sunrise;
int? _sunset;
Sys({
int? type,
int? id,
String? country,
int? sunrise,
int? sunset,
}) {
_type = type;
_id = id;
_country = country;
_sunrise = sunrise;
_sunset = sunset;
}
Sys.fromJson(dynamic json) {
_type = json['type'];
_id = json['id'];
_country = json['country'];
_sunrise = json['sunrise'];
_sunset = json['sunset'];
}
int? get type => _type;
int? get id => _id;
String? get country => _country;
int? get sunrise => _sunrise;
int? get sunset => _sunset;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['type'] = _type;
map['id'] = _id;
map['country'] = _country;
map['sunrise'] = _sunrise;
map['sunset'] = _sunset;
return map;
}
}
/// all : 40
class Clouds {
int? _all;
Clouds({
int? all,
}) {
_all = all;
}
Clouds.fromJson(dynamic json) {
_all = json['all'];
}
int? get all => _all;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['all'] = _all;
return map;
}
}
/// speed : 3.09
/// deg : 90
class Wind {
double? _speed;
int? _deg;
Wind({
double? speed,
int? deg,
}) {
_speed = speed;
_deg = deg;
}
Wind.fromJson(dynamic json) {
_speed = json['speed'];
_deg = json['deg'];
}
double? get speed => _speed;
int? get deg => _deg;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['speed'] = _speed;
map['deg'] = _deg;
return map;
}
}
/// temp : 18.73
/// feels_like : 17.94
/// temp_min : 17.67
/// temp_max : 20.4
/// pressure : 1023
/// humidity : 49
class Main {
double? _temp;
double? _feelsLike;
double? _tempMin;
double? _tempMax;
int? _pressure;
int? _humidity;
Main({
double? temp,
double? feelsLike,
double? tempMin,
double? tempMax,
int? pressure,
int? humidity,
}) {
_temp = temp;
_feelsLike = feelsLike;
_tempMin = tempMin;
_tempMax = tempMax;
_pressure = pressure;
_humidity = humidity;
}
Main.fromJson(dynamic json) {
_temp = json['temp'];
_feelsLike = json['feels_like'];
_tempMin = json['temp_min'];
_tempMax = json['temp_max'];
_pressure = json['pressure'];
_humidity = json['humidity'];
}
double? get temp => _temp;
double? get feelsLike => _feelsLike;
double? get tempMin => _tempMin;
double? get tempMax => _tempMax;
int? get pressure => _pressure;
int? get humidity => _humidity;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['temp'] = _temp;
map['feels_like'] = _feelsLike;
map['temp_min'] = _tempMin;
map['temp_max'] = _tempMax;
map['pressure'] = _pressure;
map['humidity'] = _humidity;
return map;
}
}
/// id : 802
/// main : "Clouds"
/// description : "구름조금"
/// icon : "03d"
class Weather {
int? _id;
String? _main;
String? _description;
String? _icon;
Weather({
int? id,
String? main,
String? description,
String? icon,
}) {
_id = id;
_main = main;
_description = description;
_icon = icon;
}
Weather.fromJson(dynamic json) {
_id = json['id'];
_main = json['main'];
_description = json['description'];
_icon = json['icon'];
}
int? get id => _id;
String? get main => _main;
String? get description => _description;
String? get icon => _icon;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['id'] = _id;
map['main'] = _main;
map['description'] = _description;
map['icon'] = _icon;
return map;
}
}
/// lon : 9.19
/// lat : 45.4642
class Coord {
double? _lon;
double? _lat;
Coord({
double? lon,
double? lat,
}) {
_lon = lon;
_lat = lat;
}
Coord.fromJson(dynamic json) {
_lon = json['lon'];
_lat = json['lat'];
}
double? get lon => _lon;
double? get lat => _lat;
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['lon'] = _lon;
map['lat'] = _lat;
return map;
}
}
loading.dart 수정
import 'package:weather/model/current_weather.dart';
void getLocation() async {
MyLocation myLocation = MyLocation();
await myLocation.getMyCurrentLocation();
latitude = myLocation.latitude;
longitude = myLocation.longitude;
debugPrint('loading.dart >> ' + latitude.toString() +' / ' +longitude.toString());
String baseApi = 'https://api.openweathermap.org/data/2.5/weather';
Network network = Network(
'$baseApi?lat=${latitude.toString()}&lon=${longitude.toString()}&appid=$apiKey&units=metric');
var weatherData = await network.getJsonData();
debugPrint(weatherData.toString());
// 추가된 부분 //
CurrentWeather currentWeather = CurrentWeather.fromJson(weatherData);
debugPrint(currentWeather.name);
// 추가된 부분 //
// weatherData 대신 currentWeather 전달 //
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WeatherScreen(weatherData: currentWeather)));
}
전체 버전은 더보기 클릭 ==>
더보기
import 'package:flutter/material.dart';
import 'package:weather/data/my_location.dart';
import 'package:weather/data/network.dart';
import 'package:weather/model/current_weather.dart';
import 'package:weather/screens/weather_screen.dart';
const apiKey = '1e1a2b8f6d9b5311cd82d001e7b20131';
class Loading extends StatefulWidget {
const Loading({Key? key}) : super(key: key);
@override
_LoadingState createState() => _LoadingState();
}
class _LoadingState extends State<Loading> {
late double latitude;
late double longitude;
@override
void initState() {
// TODO: implement initState
super.initState();
getLocation();
// fetchData();
}
void getLocation() async {
MyLocation myLocation = MyLocation();
await myLocation.getMyCurrentLocation();
latitude = myLocation.latitude;
longitude = myLocation.longitude;
debugPrint('loading.dart >> ' + latitude.toString() +' / ' +longitude.toString());
String baseApi = 'https://api.openweathermap.org/data/2.5/weather';
Network network = Network(
'$baseApi?lat=${latitude.toString()}&lon=${longitude.toString()}&appid=$apiKey&units=metric');
var weatherData = await network.getJsonData();
debugPrint(weatherData.toString());
CurrentWeather currentWeather = CurrentWeather.fromJson(weatherData);
debugPrint(currentWeather.name);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WeatherScreen(weatherData: currentWeather)));
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () {
debugPrint('ElevatedButton clicked~~');
},
child: const Text(
'Get my location',
style: TextStyle(color: Colors.white),
),
),
),
);
}
}
weather_screen.dart 수정
변수 타입 및 하위 필드 정보 접근 방식이 수정되었다.
전체 버전은 더보기 클릭 ==>
더보기
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:weather/model/current_weather.dart';
class WeatherScreen extends StatefulWidget {
final CurrentWeather weatherData;
const WeatherScreen({Key? key, required this.weatherData}) : super(key: key);
@override
State<WeatherScreen> createState() => _WeatherScreenState();
}
class _WeatherScreenState extends State<WeatherScreen> {
late String cityName;
late int temp;
late String currentDate;
@override
void initState() {
// TODO: implement initState
super.initState();
updateData(widget.weatherData);
}
void updateData(CurrentWeather weatherData) {
var dt = weatherData.dt!;
var timezone = weatherData.timezone!;
var tempTime = DateTime.fromMillisecondsSinceEpoch((dt+timezone) * 1000);
cityName = weatherData.name!;
temp = weatherData.main!.temp!.round();
currentDate = DateFormat('yyyy-MM-dd, HH:mm:ss').format(tempTime);
debugPrint('cityName[$cityName], temp[${weatherData.main!.temp}]');
debugPrint('dt[$dt], timezone[$timezone], Date[$currentDate]');
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(cityName, style: const TextStyle(fontSize: 30)),
const SizedBox(height: 40),
Text(currentDate, style: const TextStyle(fontSize: 30)),
const SizedBox(height: 40),
Text(temp.toString(), style: const TextStyle(fontSize: 30)),
],
),
),
),
);
}
}
콘솔로그
I/flutter ( 7182): loading.dart >> 45.4642033 / 9.1899817
I/flutter ( 7182): {coord: {lon: 9.1914, lat: 45.4642}, weather: [{id: 800, main: Clear, description: clear sky, icon: 01d}], base: stations, main: {temp: 20.39, feels_like: 19.61, temp_min: 18.39, temp_max: 22.21, pressure: 1022, humidity: 43}, visibility: 10000, wind: {speed: 3.09, deg: 150}, clouds: {all: 0}, dt: 1651147232, sys: {type: 2, id: 2012644, country: IT, sunrise: 1651119376, sunset: 1651170298}, timezone: 7200, id: 3173435, name: Milan, cod: 200}
I/flutter ( 7182): Milan
I/flutter ( 7182): cityName[Milan], temp[20.39]
I/flutter ( 7182): dt[1651147232], timezone[7200], Date[2022-04-28, 14:00:32]
화면 출력
'Flutter > 10 app Weather' 카테고리의 다른 글
[Flutter] App Weather - 5단계 추가 데이터 & 모델링 (0) | 2022.04.29 |
---|---|
[Flutter] App Weather - 4단계 UI (0) | 2022.04.29 |
[Flutter] App Weather - 3단계 json from openweathermap (0) | 2022.04.28 |
[Flutter] App Weather - 2단계 http & json (0) | 2022.04.27 |
[Flutter] App Weather - 1단계 geolocator 8.2.0 (0) | 2022.04.27 |