Last active
September 3, 2020 09:59
-
-
Save manofi21/de6ed002bdea1c6a865cbcfa3aca8053 to your computer and use it in GitHub Desktop.
di sini sudah => flutter_bloc: ^0.20.0. File yang berada dalam folder yang sama ada bloc.dart, weather_bloc.dart, weather_event.dart, weather_state.dart . Folder dan semua file(kecuali bloc.dart) akan dibuat otomatis dengan bantuan extention yang di download dari VSCode, yaitu bloc. Dengan click kanan dan pilih, "New Bloc" . bloc.dart dibuat manual
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// di file ini, berfungsi untuk menyambungkan 3 file di folder yang sama, agar di setiap file tidak perlu | |
// menulis import untuk mangambil class di file berbeda. | |
// dan tanpa ini bloc dari folder berbeda tidak akan berjalan | |
export 'weather_bloc.dart'; | |
export 'weather_event.dart'; | |
export 'weather_state.dart'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter_bloc/flutter_bloc.dart'; | |
import 'package:flutter_grocery_shopping/model.dart'; | |
import 'bloc/bloc.dart'; | |
import 'bloc/weather_bloc.dart'; | |
class WeatherPage extends StatefulWidget { | |
WeatherPage({Key key}) : super(key: key); | |
_WeatherPageState createState() => _WeatherPageState(); | |
} | |
class _WeatherPageState extends State<WeatherPage> { | |
final weatherBloc = WeatherBloc(); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text("Fake Weather App"), | |
), | |
body: Container( | |
padding: EdgeInsets.symmetric(vertical: 16), | |
alignment: Alignment.center, | |
child: BlocProvider( | |
builder: (context) => weatherBloc, | |
child: BlocListener( | |
bloc: weatherBloc, | |
listener: (context, WeatherState state) { | |
if (state is WeatherLoaded) { | |
print('${state.weather.cityName}'); | |
} | |
}, | |
child: BlocBuilder( | |
bloc: weatherBloc, | |
builder: (BuildContext context, WeatherState state) { | |
// jika state yang muncul pertama WeatherInitial, Widget yang dipaggil | |
// buildInitialInput | |
if (state is WeatherInitial) { | |
return buildInitialInput(); | |
} | |
// jika state yang muncul WeatherLoading, Widget yang dipanggil | |
// buildLoading | |
else if (state is WeatherLoading) { | |
return buildLoading(); | |
} | |
// jika state yang muncul WeatherLoading, Widget yang dipanggil | |
// buildColumnWithData(state.weather); | |
else if (state is WeatherLoaded) { | |
return buildColumnWithData(state.weather); | |
} | |
}), | |
), | |
), | |
), | |
); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
weatherBloc.dispose(); | |
} | |
} | |
Column buildColumnWithData(Weather weather) { | |
return Column( | |
mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |
children: <Widget>[ | |
Text( | |
weather.cityName, | |
style: TextStyle( | |
fontSize: 40, | |
fontWeight: FontWeight.w700, | |
), | |
), | |
Text( | |
"${weather.temperature.toStringAsFixed(1)} °C", | |
style: TextStyle(fontSize: 80), | |
), | |
CityInputField(), | |
], | |
); | |
} | |
Widget buildInitialInput() { | |
return Center( | |
child: CityInputField(), | |
); | |
} | |
Widget buildLoading() { | |
return Center( | |
child: CircularProgressIndicator(), | |
); | |
} | |
class CityInputField extends StatefulWidget { | |
const CityInputField({ | |
Key key, | |
}) : super(key: key); | |
@override | |
_CityInputFieldState createState() => _CityInputFieldState(); | |
} | |
class _CityInputFieldState extends State<CityInputField> { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 50), | |
child: TextField( | |
onSubmitted: submitCityName, | |
textInputAction: TextInputAction.search, | |
decoration: InputDecoration( | |
hintText: "Enter a city", | |
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), | |
suffixIcon: Icon(Icons.search), | |
), | |
), | |
); | |
} | |
void submitCityName(String cityName) { | |
final weatherBloc = BlocProvider.of<WeatherBloc>(context); | |
// mengambil string dari input user dan mengganti event menjadi GetWeather | |
weatherBloc.dispatch(GetWeather(cityName)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter_bloc/flutter_bloc.dart'; | |
import 'bloc/bloc.dart'; | |
import 'bloc/model.dart'; | |
import 'bloc/weather_bloc.dart'; | |
// Output yang di hasilkan sama, hanya saja di BLoC yang ini, Widget / BloCBuilder-nya bisa ditempatkan diluar | |
// BloCProvider | |
class WeatherPage extends StatefulWidget { | |
WeatherPage({Key key}) : super(key: key); | |
_WeatherPageState createState() => _WeatherPageState(); | |
} | |
class _WeatherPageState extends State<WeatherPage> { | |
final weatherBloc = WeatherBloc(); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: Text("Fake Weather App"), | |
), | |
body: BlocProvider( | |
// Widget yang ditempatkan di luar BlocProvider harus berdiri sendiri/ Bukan menjadi method. Jadi harus berada di dalam | |
// stateless atau statefull | |
builder: (context) => weatherBloc, child: WeatherPageChild())); | |
// build been changes to create // | |
create: (context) => weatherBloc, child: WeatherPageChild())); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
weatherBloc.dispose(); | |
// dispose has been changes to close // | |
weatherBloc.close(); | |
} | |
} | |
class WeatherPageChild extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
padding: EdgeInsets.symmetric(vertical: 16), | |
alignment: Alignment.center, | |
child: BlocListener<WeatherBloc, WeatherState>( | |
bloc: BlocProvider.of<WeatherBloc>(context), | |
// bloc been changes to cubit // | |
cubit: BlocProvider.of<WeatherBloc>(context), | |
listener: (context, WeatherState state) { | |
if (state is WeatherLoaded) { | |
print('${state.weather.cityName}'); | |
} | |
}, | |
// untuk dapat menyambungkannya dengan BLoCProvider masukkan WeatherBloC dan WeatherState // | |
child: BlocBuilder<WeatherBloc, WeatherState>( | |
bloc: BlocProvider.of<WeatherBloc>(context), | |
// widget yang di dalam BlocBuilder tidak perlu lagi menggunakan BlocBuilder // | |
// bloc been changes to cubit // | |
cubit: BlocProvider.of<WeatherBloc>(context), | |
builder: (BuildContext context, WeatherState state) { | |
if (state is WeatherInitial) { | |
return buildInitialInput(); | |
} else if (state is WeatherLoading) { | |
return buildLoading(); | |
} else if (state is WeatherLoaded) { | |
return buildColumnWithData(state.weather); | |
} | |
}), | |
), | |
); | |
} | |
} | |
Column buildColumnWithData(Weather weather) { | |
return Column( | |
mainAxisAlignment: MainAxisAlignment.spaceEvenly, | |
children: <Widget>[ | |
Text( | |
weather.cityName, | |
style: TextStyle( | |
fontSize: 40, | |
fontWeight: FontWeight.w700, | |
), | |
), | |
Text( | |
"${weather.temperature.toStringAsFixed(1)} °C", | |
style: TextStyle(fontSize: 80), | |
), | |
CityInputField(), | |
], | |
); | |
} | |
Widget buildInitialInput() { | |
return Center( | |
child: CityInputField(), | |
); | |
} | |
Widget buildLoading() { | |
return Center( | |
child: CircularProgressIndicator(), | |
); | |
} | |
// widget yang membutuhkan method dispact / meminta sistem memasukkan input ke BLoC pattern | |
// juga harus berdiri sendiri | |
class CityInputField extends StatefulWidget { | |
const CityInputField({ | |
Key key, | |
}) : super(key: key); | |
@override | |
_CityInputFieldState createState() => _CityInputFieldState(); | |
} | |
class _CityInputFieldState extends State<CityInputField> { | |
@override | |
Widget build(BuildContext context) { | |
return Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 50), | |
child: TextField( | |
onSubmitted: submitCityName, | |
textInputAction: TextInputAction.search, | |
decoration: InputDecoration( | |
hintText: "Enter a city", | |
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12)), | |
suffixIcon: Icon(Icons.search), | |
), | |
), | |
); | |
} | |
void submitCityName(String cityName) { | |
final weatherBloc = BlocProvider.of<WeatherBloc>(context); | |
weatherBloc.dispatch(GetWeather(cityName)); | |
// dispatch been changes to add // | |
weatherBloc.add(GetWeather(cityName)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'dart:math'; | |
import 'package:bloc/bloc.dart'; | |
import '../model.dart'; | |
import './bloc.dart'; | |
// Event dan State dari folder _Event dan _State harus Sesuai // | |
class WeatherBloc extends Bloc<WeatherEvent, WeatherState> { | |
// inisiasi state pertama ketika bloc dipanggil atau aplikasi baru dijalankan // | |
@override | |
WeatherState get initialState => WeatherInitial(); | |
@override | |
Stream<WeatherState> mapEventToState( | |
// tambah WeatherEvent // | |
WeatherEvent event, | |
) async* { | |
// get values in current bloc's state // | |
int score = state.props[3]; | |
// event yang diminta hanya satu dan memiliki parameter // | |
if (event is GetWeather) { | |
// Outputting a state from the asynchronous generator // | |
// jika event GetWeather state pertama dijalankan WeatherLoadin // | |
yield WeatherLoading(); | |
// kemudia inisialisasi dengan await dan buat method menyimpan input user dari // | |
// WeatherEvent dan menampilkannya // | |
final weather = await _fetchWeatherFromFakeApi(event.cityName); | |
// masukkan inisialisasi diatas ke WeatherLoaded // | |
yield WeatherLoaded(weather); | |
} | |
} | |
Future<Weather> _fetchWeatherFromFakeApi(String cityName) { | |
// Simulate network delay | |
return Future.delayed( | |
Duration(seconds: 1), | |
() { | |
return Weather( | |
cityName: cityName, | |
// nilai yang dimasukkan random // | |
// Temperature between 20 and 35.99 // | |
temperature: 20 + Random().nextInt(15) + Random().nextDouble(), | |
); | |
}, | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:equatable/equatable.dart'; | |
import 'package:meta/meta.dart'; | |
// event di sini akan menyimpan string yang di input user // | |
abstract class WeatherEvent extends Equatable { | |
WeatherEvent([List props = const []]) :super(props); | |
} | |
class GetWeather extends WeatherEvent { | |
final String cityName; | |
GetWeather(this.cityName) : super([cityName]); | |
} | |
// versi baru untuk equetable // | |
import 'package:equatable/equatable.dart'; | |
import 'package:meta/meta.dart'; | |
// event di sini akan menyimpan string yang di input user // | |
abstract class WeatherEvent extends Equatable{ | |
const WeatherEvent(); | |
} | |
class GetWeather extends WeatherEvent { | |
final String cityName; | |
GetWeather(this.cityName); | |
@override | |
List<Object> get props => [cityName]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import '../model.dart'; | |
import 'package:equatable/equatable.dart'; | |
import 'package:meta/meta.dart'; | |
abstract class WeatherState extends Equatable{ | |
const WeatherState(); | |
} | |
class WeatherInitial extends WeatherState {} | |
class WeatherLoading extends WeatherState {} | |
class WeatherLoaded extends WeatherState { | |
final Weather weather; | |
WeatherLoaded(this.weather) : super([weather]); | |
} | |
// untuk versi baru equerable // | |
class WeatherInitial extends WeatherState { | |
@override | |
List<Object> get props => []; | |
} | |
class WeatherLoading extends WeatherState { | |
@override | |
List<Object> get props => []; | |
} | |
class WeatherLoaded extends WeatherState { | |
final Weather weather; | |
WeatherLoaded(this.weather); | |
@override | |
List<Object> get props => [weather]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment