如何使用 shared_preferences 库实现 Flutter Riverpod FutureProvider?

问题描述

我目前没有 FutureProvider + shared_preferences 的实现:

class IdentityModel {
  final bool isLoggedIn;
  final int id;
  final String userName;
  final String avatarUrl;

  const IdentityModel({
    this.isLoggedIn = false,this.id,this.userName,this.avatarUrl,});
}

class IdentityNotifier extends StateNotifier<IdentityModel> {
  IdentityNotifier() : super(_initialState);

  static final _initialState = IdentityModel();

  void loginAction(MyCustomUserClass user) {
    state = IdentityModel(
      isLoggedIn: true,id: user.id,userName: user.userName,avatarUrl: user.avatarUrl,);
  }

  void logoutAction() {
    state = IdentityModel(
      isLoggedIn: false,id: null,userName: null,avatarUrl: null,);
  }
}

final identityProvider = StateNotifierProvider<IdentityNotifier>(
  (ref) => IdentityNotifier(),);

我想使用 shared_preferences 包保持状态,但我不太确定如何将我当前的实现转换为使用 FutureProvider 的实现,因为 shared_preferences 使用 {{1} } 获取/设置。

我基本上想从 async/await 中“加载”,使用它的 shared_preferences 方法在应用程序启动时初始化通知程序,然后在通知程序中调用 get shared_preferences 方法方法 setloginAction

解决方法

如果您的 IdentityNotifier 依赖于 Future,则它应该是 StateNotifier 这允许您在 Future 尚未加载或出现错误时在 UI 上显示不同的信息。

class IdentityNotifier extends StateNotifier<AsyncValue<IdentityModel>> {
  IdentityNotifier({this.prefs}) : super(AsyncLoading());
  final SharedPreferences prefs;

  void init() {
    /// check user & get state from prefs
    state = AsyncData(IdentityModel(id:prefs.getInt("id")));
  }

  void loginAction(MyCustomUserClass user) {
    /// set info in prefs
    state = AsyncData(IdentityModel(
      isLoggedIn: true,id: user.id,userName: user.userName,avatarUrl: user.avatarUrl,));
  }

  void logoutAction() {
    /// set info in prefs
    state = AsyncData(IdentityModel(
      isLoggedIn: false,id: null,userName: null,avatarUrl: null,));
  }
}

让你的提供者依赖于未来的提供者:

final identityProvider = StateNotifierProvider<IdentityNotifier>((ref) {
  
  return ref.watch(_sharedPref).when(
      data: (prefs){
        final identityNotifier =  IdentityNotifier(prefs: prefs);
        identityNotifier.init();
        return identityNotifier;
      },loading: () => IdentityNotifier(),error: (_,__) => throw "error" /// throw or set an error state in your notifier
      );
  
});

final FutureProvider<SharedPreferences> _sharedPref =
    FutureProvider((ref) async => SharedPreferences.getInstance());

您的 IDNotifier 将加载的第一帧您可以显示 CircularIndicator... 接下来,当加载 sharedPref 实例时,IdNotifier 将使用首选项引用重新实例化,并且 init 方法设置您的用户数据

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...