Sura Manager

ValueNotifier and ValueListenableBuilder but for asynchronous value.

pub package Latest commit


Add this to pubspec.yaml

  sura_manager: ^1.5.0

Use case and motivation:

Now imagine that you're fetching data from an API or working with a Future function that reflects the change to UI. Traditionally you could use setState or FutureBuilder to handle this case. But both of them create a boilerplate code and lack some functionality like refresh, event callback ..etc.

FutureManager provides you a solution with mainly focus on 3 main state of Future value: Loading,Error and Done where you can handle the UI with those states with FutureManagerBuilder.

Short example:

//Create a manager
FutureManager<int> dataManager = FutureManager();

//define a Future function
dataManager.asyncOperation(() => doingSomeAsyncWorkAndReturnValueAsInt());

//Handle the value
Widget(BuildContext context){
  return FutureManagerBuilder<int>(
      futureManager: dataManager,
      error: (error) => YourErrorWidget(error), //optional
      loading: YourLoadingWidget(), //optional
      ready: (context, data){
        return ElevatedButton(
          child: Text("My data: ${data}"),
          onPressed: (){


futureFunctiona function to run and return datanull
reloadingReset a state to loading or not when you call refresh or asyncOperationtrue
onSuccessa callback function called after operation is successnull
onDonea callback function called after operation is completely done, similar to finally in try-catchnull
onErrora callback function called after operation has an errornull
cacheOptionan option to cache data.non
datacurrent data in the Manager
errorerror in the Manager
hasDatacheck if our Manager has a data
hasErrorcheck if our Manager has an error
futurefuture field of the current futureFunction
isRefreshingcheck if our Manager is refreshing
whenA method similar to FutureManagerBuilder
asyncOperationrun futureFunction that will return a data to our Manager
refreshcall the asyncOperation again. we have to assign futureFunction from the constructor or call asyncOperation once to run this method, otherwise it will log an error
updateDataa method to update data in our Manager
modifyDataa method to update data in our Manager with data callback, prefer using this method to update data.
resetDatareset everything to loading or null state
addErroradd error into our manager
clearErrorclear error in the manager but only work if ViewState isn't in error state



class _HomePageState extends State<NewPage> {

  FutureManager<int> dataManager = FutureManager();
  void initState() {
      await Future.delayed(Duration(seconds: 2));
      //Add 10 into our dataManager
      return 10;

  void dispose() {

  Widget build(BuildContext context) {
    //Use with FutureManagerBuilder
    return Scaffold(
      appBar: AppBar(
        actions: [
              //call our asyncOperation again
      body: FutureManagerBuilder<int>(
        futureManager: dataManager,
        error: (error) => YourErrorWidget(),
        loading: YourLoadingWidget(),
        ready: (context, data){
          //result: My data: 10
          return Text("My data: ${data}"),


futureManagerour FutureManager objectrequired
readyA widget builder show when FutureManager has a datarequired
loadingA widget show when FutureManager state is loadingCircularProgressIndicator
errorA widget show when FutureManager state is errorText(error.toString())
onErrorA callback function that call when FutureManager state is errornull
onDataA callback function that call when FutureManager state has a data or data is updatednull
onRefreshingA widget to show on top of this widget when refreshingnull

Ecosystem and usage

  • Q: when to use cacheOption? A: When you have a global manager and want to preserve data on a period of time without running asyncOperation logic or futureFunction again.
  • Q: when to use ManagerProvider? A: When you want to use FutureManager across multiple widget(but not global) without declaring it as a global variable. By doing this, FutureManager will be auto dispose and recreate each time its first used. This work the same way as Riverpod with autoDispose.