This package is inspired by the Union type provided by freezed
package. But sometimes, it could be too complicating or you join a legacy project or a team project that it’s not ready to migrate to that package.
Fetching_state for simplification
Most of the time, in your app, you have to fetch remote data that would take a while after sending the request until obtaining the data. That is where and when you want to display something like a Loading Indicator and then either a successful fetched content or error content.
Normally, we would you some boolean state to indicate whether data is being fetched, another state for notifying error. Follow by some if else
statements.
That’s why I create the package fetching_state
. This package helps you to handle fetching state easier and cleaner, get rid of those if else
statements when data is fetching, finished fetching, or error on fetching even an init state that lives before those ones.
Features of fetching_state package
- Get rid of
if
else
statements in UI - Decide what to display when fetching remote data in 4 states [
init
,loading
,done
,error
] - Option to pass the data or error objects in
onDone
andonError
Usage of fetching_state
In this example, for the sake of simplification, we use a stateful widget. But this package and be used with any state management solution.
create a fetching state with init state _fetching = FetchingState.init();
and then, depending on the state of your app we can set it to appropriate status as follow
_fetching = FetchingState.loading();
_fetching = FetchingState.done()
_fetching = FetchingState.error()
In the build method, you can use when
or whenOrElse
method to build the corresponding widget.
For more options, you can pass data into FetchingState.done({T? data})
and FetchingState.error({E? error})
. These data later can be accessed in: R Function(T? data) onDone
, R Function(E? error) onError
when you declare your when
method as in the example.
return _fetching.when(
onInit: () => const Text(
'INIT',
style: TextStyle(color: Colors.blue),
),
onDone: (text) => Text(
text!,
style: const TextStyle(color: Colors.green),
),
onError: (error) => Text(
error!,
style: const TextStyle(color: Colors.red),
),
onLoading: () => const CircularProgressIndicator(),
);
for more details, please visit: https://pub.dev/packages/fetching_state
Full Example
import 'package:fetching_state/fetching_state.dart';
import 'package:flutter/material.dart';
void main() {
runApp(
const MyApp(),
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetchin State Example',
theme: ThemeData(
primarySwatch: Colors.blue,
textTheme: const TextTheme(
bodyText2: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
home: const Example(),
);
}
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
late FetchingState<String, String> _fetching;
@override
void initState() {
_fetching = FetchingState.init();
super.initState();
}
Future<void> getDone() async {
setState(() {
_fetching = FetchingState.loading();
});
await Future.delayed(const Duration(milliseconds: 500));
setState(() {
_fetching = FetchingState.done(data: 'DONE IN STATE');
});
}
Future<void> getError() async {
setState(() {
_fetching = FetchingState.loading();
});
await Future.delayed(const Duration(milliseconds: 500));
setState(() {
_fetching = FetchingState.error(error: 'Error IN STATE');
});
}
Future<void> getInit() async {
setState(() {
_fetching = FetchingState.loading();
});
await Future.delayed(const Duration(milliseconds: 500));
setState(() {
_fetching = FetchingState.init();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Center(
child: Builder(
builder: (context) {
return _fetching.when(
onInit: () => const Text(
'INIT',
style: TextStyle(color: Colors.blue),
),
onDone: (text) => Text(
text!,
style: const TextStyle(color: Colors.green),
),
onError: (error) => Text(
error!,
style: const TextStyle(color: Colors.red),
),
onLoading: () => const CircularProgressIndicator(),
);
},
),
),
const SizedBox(
height: 40,
),
ElevatedButton(
onPressed: getDone,
child: const Text('Done'),
),
ElevatedButton(
onPressed: getError,
child: const Text('Error'),
),
ElevatedButton(
onPressed: getInit,
child: const Text('Init'),
),
],
),
),
);
}
}