-1

So I have some question abaout how to correctly use FutureBuilder. I read somewhere that we should store the future in a variable and call that variable in the FutureBuilder instead of the future service. But how do we initalize the initial value of that variable? When I tired this, it always gives LateInitializationError: Field '_dataFuture@28307501' has not been initialized. and should wait until the data is loaded.

  late Future<List<TransaksiResp>> _dataFuture;

  @override
  void initState() {
    super.initState();
    transaksiService = TransaksiService();
    getUserPrefs().then((value) {
      setState(() {
        _dataFuture = transaksiService.getTransaksi(user[2]);});
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      body: Column(
        children: <Widget>[
          Flexible(
            child: SizedBox(
              child: FutureBuilder<List<TransaksiResp>>(
                future: _dataFuture,
                builder: (BuildContext context, AsyncSnapshot snapshot) {
                  if(snapshot.hasError) {
                    print(snapshot);
                    return Center(
                      child: Text("Error"),
                    );
                  } else if (snapshot.hasData){
                    List<TransaksiResp> response = snapshot.data;
                    return _buildListView(response);
                  } else {
                    return Center(
                      child: Container(),
                    );
                  }
                },
              ),
            ),
          )
        ],
      ),
    );
  }

This is getUserPrefs method to get user data from Shared Preference

 Future<void> getUserPrefs() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    user = prefs.getStringList("user")!;
    setState(() {});
  }
Ananda Pramono
  • 899
  • 1
  • 6
  • 18
  • you should use `_dataFuture = someMethodReturningYourFuture();` inside `initState` – pskink Sep 17 '21 at 05:58
  • already put it in initState, right after calling `getUserPrefs`, or should I call it directly inside `initState?` Because I need the data from `getUserPrefs` to call for the service – Ananda Pramono Sep 17 '21 at 06:08
  • no, you are assigning `_dataFuture = ...` inside `.then` callback that is called after `build` method is called - to check it add one `print('build')` inside `build()` method and another `print('then')` inside `.then` callback – pskink Sep 17 '21 at 06:10
  • basically you should use `_dataFuture = someMethodReturningYourFuture();` without any `setState` etc, just write an `async` method that returns a `Future`, for more read [Asynchronous programming: futures, async, await](https://dart.dev/codelabs/async-await) – pskink Sep 17 '21 at 06:16

2 Answers2

1

Get the answer, because I need the data from SharedPreferences, I need to wait for the function to finish first

  _getService() async {
    await getUserPrefs();
    return await transaksiService.getTransaksi(user[2]);
  }

Then calling it in iniState and save it in a variable

 _dataFuture = _getService();
Ananda Pramono
  • 899
  • 1
  • 6
  • 18
  • btw you can just call `return transaksiService.getTransaksi(user[2]);` - no need for `await` here, also i would return user data from `getUserPrefs` so you can avoid global `user` variable / field: `final user = await getUserPrefs();` – pskink Sep 17 '21 at 06:56
0
  • FutureBuilder removes boilerplate code.

  • FutureBuilder Widget is used to create widgets based on the latest snapshot of interaction with a Future. It is necessary for Future to be obtained earlier either through a change of state or change in dependencies.

If you get data from API refer my answer here or here or here hope it's helpful to you in this examples I have used FutureBuilder refer it.

refer documentation here for FutureBuilder

You aslo refer here

Hope its help to you

Ravindra S. Patil
  • 11,757
  • 3
  • 13
  • 40