Created
August 9, 2022 04:00
-
-
Save ltvu93/54bf7073ec591d373e3befefb0284a03 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 'dart:math'; | |
const Color darkBlue = Color.fromARGB(255, 18, 32, 47); | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
theme: ThemeData.dark().copyWith( | |
scaffoldBackgroundColor: darkBlue, | |
), | |
debugShowCheckedModeBanner: false, | |
home: const DetailScreen(), | |
); | |
} | |
} | |
class DetailScreen extends StatefulWidget { | |
const DetailScreen({Key? key}) : super(key: key); | |
@override | |
State<DetailScreen> createState() => _DetailScreenState(); | |
} | |
class _DetailScreenState extends State<DetailScreen> { | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
body: SafeArea( | |
child: BlocProvider( | |
create: (context) => DetailCubit()..getData(), | |
child: BlocListener<DetailCubit, DetailState>( | |
listener: (context, state) { | |
if (state is DetailApproveError) { | |
ScaffoldMessenger.of(context).showSnackBar( | |
SnackBar( | |
backgroundColor: Colors.red, | |
content: Text( | |
state.error.toString(), | |
style: const TextStyle( | |
color: Colors.white, | |
), | |
), | |
), | |
); | |
} else if (state is DetailApproveSuccess) { | |
ScaffoldMessenger.of(context).showSnackBar( | |
const SnackBar( | |
content: Text('Approve success'), | |
), | |
); | |
} | |
}, | |
child: BlocBuilder<DetailCubit, DetailState>( | |
builder: (context, state) { | |
switch (state.runtimeType) { | |
case DetailInit: | |
return const SizedBox(); | |
case DetailInitLoading: | |
return const Center( | |
child: CircularProgressIndicator(), | |
); | |
case DetailInitError: | |
return Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: [ | |
Text( | |
(state as DetailInitError).error.toString(), | |
), | |
const SizedBox(height: 8), | |
ElevatedButton( | |
onPressed: () { | |
context.read<DetailCubit>().getData(); | |
}, | |
child: const Text('Reload'), | |
), | |
], | |
), | |
); | |
case DetailLoaded: | |
case DetailApproveLoading: | |
case DetailApproveError: | |
case DetailApproveSuccess: | |
return Stack( | |
children: [ | |
Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: [ | |
Text( | |
'Data Loaded ${(state as DetailLoaded).data}', | |
), | |
const SizedBox(height: 8), | |
ElevatedButton( | |
onPressed: () { | |
context.read<DetailCubit>().approve(); | |
}, | |
child: const Text('Approve'), | |
), | |
], | |
), | |
), | |
if (state is DetailApproveLoading) | |
const SizedBox.expand( | |
child: Center( | |
child: CircularProgressIndicator(), | |
), | |
), | |
], | |
); | |
default: | |
print('Error $state'); | |
return const SizedBox(); | |
} | |
}, | |
), | |
), | |
), | |
), | |
); | |
} | |
} | |
abstract class DetailState {} | |
class DetailInit extends DetailState {} | |
class DetailInitLoading extends DetailState {} | |
class DetailLoaded extends DetailState { | |
final String data; | |
DetailLoaded(this.data); | |
} | |
class DetailInitError extends DetailState { | |
final Exception error; | |
DetailInitError(this.error); | |
} | |
class DetailApproveLoading extends DetailLoaded { | |
DetailApproveLoading(super.data); | |
} | |
class DetailApproveSuccess extends DetailLoaded { | |
DetailApproveSuccess(super.data); | |
} | |
class DetailApproveError extends DetailLoaded { | |
final Exception error; | |
DetailApproveError(super.data, this.error); | |
} | |
class DetailCubit extends Cubit<DetailState> { | |
DetailCubit() : super(DetailInit()); | |
Future<String> callApi(String callerName) async { | |
await Future.delayed(const Duration(seconds: 1)); | |
final random = Random().nextInt(100); | |
if (random % 2 == 0) { | |
return random.toString(); | |
} else { | |
throw Exception('$callerName error happened'); | |
} | |
} | |
Future<void> getData() async { | |
try { | |
emit(DetailInitLoading()); | |
final data = await callApi('Get data'); | |
emit(DetailLoaded(data)); | |
} on Exception catch (e) { | |
emit(DetailInitError(e)); | |
} | |
} | |
Future<void> approve() async { | |
try { | |
emit(DetailApproveLoading((state as DetailLoaded).data)); | |
await callApi('Approve'); | |
emit(DetailApproveSuccess((state as DetailLoaded).data)); | |
} on Exception catch (e) { | |
emit(DetailApproveError((state as DetailLoaded).data, e)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment