admin管理员组

文章数量:1404923

I am having trouble with Dart's asnyc programming.

-- In short --

At some point in the code I need to get rid of asynchronicity, becasue a call chains up to a synchronous method. And I cannot find a way to wait until an asynchronous call completes.

-- In detail --

I want to build an AppSettings class that I an use as a persistent store for application settings. Since I want to use it when building Widgets, I must ensure it provides synchronous calls because the Widget builder does not support await (async) calls. Alright, I know there is a FutureBuilder<T> alternatives, but I don't want to go that far. So once again, AppSettings class has to have snychronous methods.

Based on above I need to back up AppSettings with SharedPreferencesWithCache in order to have sync calls. So I built an AppSettings class that is essentially a wrapper around it, and has getters and setters for various settings.

The problem is that I am unable to ensure AppSettings can service requests, since I have no way to make sure the underlying service (SharedPreferencesWithCache) is available at a given point in time. I assumed Future.wait() will accomplish this, but apparently I was wrong and it has a different goal.

Look at below example. The serious problem is that getSensorStatusPeriod() will return the hardcoded default value of 24 until _prefs is initialized, and I have no conterl over this behaviour.

class AppSettings {
  SharedPreferencesWithCache? _prefs;

  AppSettings() {
    Future.wait([_loadPrefs()]);
  }

  Future<void> _loadPrefs() async {
    _prefs = await SharedPreferencesWithCache.create(cacheOptions: SharedPreferencesWithCacheOptions());
  }

  /// Gets the time period in hours that is used for sensor status query
  int get getSensorStatusPeriod {
    return _prefs?.getInt('sensorStatePeriod') ?? 24;
  }

  /// Sets the time period in hours that is used for sensor status query
  set setSensorStatusPeriod(int value) {
    _prefs?.setInt('sensorStatePeriod', value);
  }
}

So how in the end can I ensure the synchronous call works as expected ? In other words, how can I wait until an async operation completes ?

Ideally I didn't want to use nullable variable for _prefs and use late initialization but, yet again, I can't, because late initialization fails on class instantiation

class AppSettings {
  late SharedPreferencesWithCache _prefs; //<-- will fail late init check

  AppSettings() {
    Future.wait([_loadPrefs()]); //<-- won't wait until call completes
  }

  Future<void> _loadPrefs() async {
    _prefs = await SharedPreferencesWithCache.create(cacheOptions: SharedPreferencesWithCacheOptions());
  }

--- More generally ---

All in all, where are the various synchronization primitieves like events, semaphores, critical sections, etc. in Dart/Flutter ? How can one live without them when it comes to asnychronous programming ? In the first place, how do you snychronize code running in parallel and how do you ensure an action completes prior to another, dependent action ?

Maybe this is due to my.NET background but I actually find it a general problem in Dart, disregarding my actual issue.

本文标签: dartWait for FutureltTgt to completeStack Overflow