Skip to content

Instantly share code, notes, and snippets.

@dhruvilp
Last active May 12, 2022 12:55
Show Gist options
  • Save dhruvilp/ba09cefe0e9b1c0a8624c3e339f406ab to your computer and use it in GitHub Desktop.
Save dhruvilp/ba09cefe0e9b1c0a8624c3e339f406ab to your computer and use it in GitHub Desktop.
Flutter Workshop Demo
// Get more Flutter packages and plugins at https://pub.dev
import 'package:flutter/material.dart'; // Material UI widgets
import 'package:http/http.dart' as http; // http package
import 'dart:convert'; // json handler package
import 'defaults.dart'; // default strings and constants
// =============================================================================
// FILE: weather_model.dart
// =============================================================================
// Weather class to consume JSON data
class WeatherModel {
String? cityName;
double? temp;
double? wind;
int? humidity;
double? feelsLike;
int? pressure;
String? icon;
int? weatherId;
String? weatherType;
String? weatherDescription;
int? sunrise;
int? sunset;
WeatherModel(
this.cityName,
this.temp,
this.wind,
this.humidity,
this.feelsLike,
this.pressure,
this.icon,
this.weatherId,
this.weatherType,
this.weatherDescription,
this.sunrise,
this.sunset,
);
WeatherModel.fromJson(Map<String, dynamic> json) {
cityName = json['name'];
temp = json['main']['temp'];
wind = json['wind']['speed'];
humidity = json['main']['humidity'];
feelsLike = json['main']['feels_like'];
pressure = json['main']['pressure'];
icon = json['weather'][0]['icon'];
weatherId = json['weather'][0]['id'];
weatherType = json['weather'][0]['main'];
weatherDescription = json['weather'][0]['description'];
sunrise = json['sys']['sunrise'];
sunset = json['sys']['sunset'];
}
}
// =============================================================================
// FILE: api_service.dart
// =============================================================================
// Weather API Service class
class ApiService {
// Http [GET] request to fetch weather data for a given CITY_NAME
static Future<WeatherModel> getWeatherDataByLocation(String location) async {
// If you want to use this API, then get an APP_ID from here: https://api.openweathermap.org
var endpoint = Uri.parse(
'https://api.openweathermap.org/data/2.5/weather?q=$location&appid=$kApiKey&units=metric');
var response = await http
.get(endpoint); // Http package support GET, POST, PUT, DELETE, etc.
var body = jsonDecode(response.body);
// debugPrint("=== body === $body"); // use "debugPrint" to print values in DEV [recommended]
// // === FOR DEVELOPMENT: Use static data to avoid getting charged for API calls
// var body = jsonDecode('{"coord":{"lon":-71.0598,"lat":42.3584},"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"base":"stations","main":{"temp":15.1,"feels_like":13.79,"temp_min":13.16,"temp_max":16.43,"pressure":1017,"humidity":43},"visibility":10000,"wind":{"speed":2.06,"deg":190},"clouds":{"all":100},"dt":1651844110,"sys":{"type":2,"id":2013408,"country":"US","sunrise":1651829576,"sunset":1651880923},"timezone":-14400,"id":4930956,"name":"Boston","cod":200}');
return WeatherModel.fromJson(body);
}
}
// =============================================================================
// FILE: weather_app.dart
// =============================================================================
// =============================================================================
// Stateful WeatherApp Widget (Main UI)
//
// This widget is the "home page" of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// =============================================================================
class WeatherApp extends StatefulWidget {
final String appTitle;
const WeatherApp({
Key? key,
required this.appTitle,
}) : super(key: key);
@override
State<WeatherApp> createState() => _WeatherAppState();
}
class _WeatherAppState extends State<WeatherApp> {
WeatherModel? data;
Color? bgColor = Colors.cyan;
@override
void initState() {
getWeatherData('mumbai');
super.initState();
}
// [APPROACH 1] One way of calling an api service
void getWeatherData(String cityData) {
ApiService.getWeatherDataByLocation(cityData).then((data) {
setState(() {
data = data;
});
});
}
// [APPROACH 2] Another way of calling an api service
Future<WeatherModel> getData() async {
// new york city, los angeles, boston, chicago
data = await ApiService.getWeatherDataByLocation('mumbai');
return data!;
}
// A Widget to show weather details like Wind, Humidity, Pressure, etc
Widget _detailCard(
String name, String value, String unit, BuildContext context) {
var screenWidth = MediaQuery.of(context).size.width;
var textColor = Colors.green[100];
return Expanded(
child: Card(
color: Colors.green[900],
margin: const EdgeInsets.symmetric(horizontal: 5.0),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(50.0)),
),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Alternatively can use [Text] widget
SelectableText(
value,
style: TextStyle(
fontSize: screenWidth < 760 ? screenWidth / 12 : 45,
color: textColor,
),
),
SelectableText(
unit,
style: TextStyle(
fontWeight: FontWeight.w300,
fontSize: 15,
color: textColor,
),
),
],
),
SelectableText(
name,
style: TextStyle(
fontSize: screenWidth < 760 ? screenWidth / 20 : 25,
color: Colors.white,
),
),
],
),
),
),
);
}
// This method is rerun every time "setState" is called
@override
Widget build(BuildContext context) {
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
var screenHeight = MediaQuery.of(context).size.height;
return Scaffold(
backgroundColor: Colors.green[200],
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
actions: [
IconButton(
onPressed: () {},
icon: const Icon(
Icons.sunny,
color: Colors.black,
),
),
],
title: SelectableText(
widget.appTitle,
style: TextStyle(
color: Colors.green[900],
fontWeight: FontWeight.w600,
), // This trailing comma makes auto-formatting nicer for build methods.
),
),
body: FutureBuilder<WeatherModel>(
future: getData(),
builder:
(BuildContext context, AsyncSnapshot<WeatherModel> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
return Column(
children: [
SizedBox(
height: screenHeight < 760 ? screenHeight / 4 : 250,
width: double.infinity,
child: Stack(
alignment: Alignment.bottomCenter,
children: [
Image.network(
'https://openweathermap.org/img/wn/${data!.icon}@4x.png',
),
SelectableText(
data!.cityName.toString(),
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.brown[700],
),
),
],
),
),
const SizedBox(height: 8.0),
SelectableText(
'${data!.temp}° C', // F
style: TextStyle(
fontSize: 50,
fontWeight: FontWeight.bold,
color: Colors.green[900],
),
),
const SizedBox(height: 15.0),
SelectableText(
data!.weatherDescription!,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.green[900],
),
),
const SizedBox(height: 10.0),
Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Image.network(
'https://openweathermap.org/img/wn/01d.png'),
SelectableText(
'${DateTime.fromMillisecondsSinceEpoch(data!.sunrise! * 1000).toString().substring(11, 19)} |',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.green[900],
),
),
Image.network(
'https://openweathermap.org/img/wn/01n.png'),
SelectableText(
DateTime.fromMillisecondsSinceEpoch(
data!.sunset! * 1000)
.toString()
.substring(11, 19),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.green[900],
),
),
],
),
const Spacer(),
SizedBox(
height: 200,
width: 760,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_detailCard(
'Wind',
data!.wind.toString(),
'km',
context,
), // mph
_detailCard(
'Humidity',
data!.humidity.toString(),
'%',
context,
),
_detailCard(
'Pressure',
data!.pressure.toString(),
'mBar',
context,
), // inHg
// _detailCard(
// 'Feels like',
// data!.feelsLike.toString(),
// '° C',
// context,
// ), // ° F
],
),
),
),
const SizedBox(height: 20.0),
],
);
} else if (snapshot.connectionState == ConnectionState.waiting) {
return const CircularProgressIndicator();
}
return Container();
},
));
}
}
// A Material theme app widget
class MyApp extends StatelessWidget {
final String appTitle;
const MyApp({
Key? key,
required this.appTitle,
}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: appTitle,
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: WeatherApp(appTitle: appTitle),
);
}
}
// Dart main class
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp(appTitle: 'Weather App'));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment