Skip to content

Instantly share code, notes, and snippets.

@manofi21
Last active September 3, 2020 09:59
Show Gist options
  • Save manofi21/de6ed002bdea1c6a865cbcfa3aca8053 to your computer and use it in GitHub Desktop.
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
// 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';
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));
}
}
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));
}
}
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(),
);
},
);
}
}
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];
}
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