Flutter:在 Stream 类中访问 SharedPreferences Provider / ChangeNotifier
Posted
技术标签:
【中文标题】Flutter:在 Stream 类中访问 SharedPreferences Provider / ChangeNotifier【英文标题】:Flutter: Access SharedPreferences Provider / ChangeNotifier in a Stream Class 【发布时间】:2020-11-03 19:30:56 【问题描述】:我在 *** 中环顾四周,并没有找到解决此问题的方法。 设想: 我有一个带有 ChangeNotifier 类的 Flutter SharedPreferences Provider,它将使用当前登录用户信息进行更新。
简化内容:
class SharedPreferences
final String userId;
final String userName;
SharedPreferences(
@required this.userId,
@required this.userName,
);
class SharedPreferencesData with ChangeNotifier
var _sharedPreferencesData = SharedPreferences(
userId: 'testUserId',
userName: 'testUserName',
);
还有一个包含 DataBaseServices 类的 database.dart 文件,用于从快照中获取 FireStore 流:
class DatabaseService
final CollectionReference companiesProfilesCollection =
Firestore.instance.collection('companiesProfiles');
List<CompanyProfile> _companiesProfilesFromSnapshot(QuerySnapshot snapshot)
return snapshot.documents.map((doc)
return CompanyProfile(
docId: doc.documentID,
companyName: doc.data['companyName'] ?? '',
maxLocationsNumber: doc.data['maxLocationsNumber'] ?? 0,
maxUsersNumber: doc.data['maxUsersNumber'] ?? 0,
);
).toList();
Stream<List<CompanyProfile>> get getCompaniesProfiles
return companiesProfilesCollection
.where('userId', isEqualTo: _userIdFromProvider)
// My problem is above -----
.snapshots()
.map(_companiesProfilesFromSnapshot);
我不想获取整个 Stream 数据,因为它对于其他 Stream 来说可能很大,我只想在 .where('userId', isEqualTo:_userIdFromProvider) 下传递用户 ID。
我无法访问此类中的上下文以从 Provider 获取数据
无法将 userId 发送到 getCompaniesProfiles getter,因为 getter 不带参数
如果我将此 getter 转换为常规方法,我将无法将用户 ID 发送给它,因为它必须在 void main() runApp(MyApp()); / return MultiProvider 下运行(提供者:[ 到那时我无法使用不包含提供者信息的上下文调用 fetch sharedPreferences ...
无法弄清楚如何在此类中接收上下文作为构造函数,当我这样做时,我得到了以下只有静态成员可以在类 DatabaseService 的初始化程序中访问。
我还是一个初学者,所以如果你能与我分享处理这个问题的最佳方法,我将不胜感激。 谢谢!
**************** 通过添加以下内容重新编辑:************** 我正在尝试实现相同的场景,这是我的代码: 主文件:
return MultiProvider(
providers: [
ChangeNotifierProvider<SpData>(
create: (context) => SpData(),
),
ProxyProvider<SpData, DS>(
create: (context) => DS(),
update: (ctx, spData, previousDS)
print('ChangeNotifierProxyProvider RAN');
previousDS.dbData = spData;
return previousDS;
,
),
],
SP 文件:
class SP
final String companyId;
SP(
@required this.companyId,
);
class SpData with ChangeNotifier
var _sPData = SP(
companyId: '',
);
void setCompanyId(String cpID)
final newSharedPreferences = SP(
companyId: cpID,
);
_sPData = newSharedPreferences;
print('_spData companyId:$_sPData.companyId');
notifyListeners();
String get getCompanyId
return _sPData.companyId;
DS 文件:
class DS with ChangeNotifier
SpData dbData;
void printCompanyId()
var companyId = dbData.getCompanyId;
print('companyId from DataBase: $companyId');
SpData dbData; DS 类内部不会更新。我已经添加了打印来确定什么正在运行,什么没有运行。当我运行我的代码时,main.dart 文件中的打印函数 print('ChangeNotifierProxyProvider RAN');不运行。
我错过了什么?为什么没有触发 ChangeNotifierProxyProvider 来更新 DS 文件中的 dbData?谢谢!
【问题讨论】:
【参考方案1】:您可以为此使用ProxyProvider
。
ProxyProvider
是一个基于其他提供者构建价值的提供者。
你说你有一个MultiProvider
,所以我猜你在这个MultiProvider
中有SharedPreferencesData
提供者,然后是DatabaseService
提供者。您需要做的是将ProxyProvider
用于DatabaseService
而不是常规提供程序,并将其基于SharedPreferencesData
提供程序。
这是一个例子:
MultiProvider(
providers: [
ChangeNotifierProvider<SharedPreferencesData>(
create: (context) => SharedPreferencesData(),
),
ProxyProvider<SharedPreferencesData, DatabaseService>(
create: (context) => DatabaseService(),
update: (context, sharedPreferencesData, databaseService)
databaseService.sharedPreferencesData = sharedPreferencesData;
return databaseService;
,
dispose: (context, databaseService) => databaseService.dispose(),
),
],
child: ...
这是上面代码 sn-p 中发生的情况:
-
每次
SharedPreferencesData
发生变化时,ProxyProvider
都会调用 update
。
DatabaseService
将其 sharedPreferencesData
变量设置在 update
中。
现在您可以访问DatabaseService
实例中的sharedPreferencesData
,您可以轻松地做您想做的事。
【讨论】:
这种方法是完全合法的。但这对我不起作用,可能与我正在做的一些错误的实现有关,原因如下:当 sharedPreferencesData 第一次传递给 DatabaseService 时,它是空的。我没有在 sharedPreferencesData 中使用 notifyListeners,因为我收到一个错误:构建错误:无法 notifyListeners => setState => 在构建应用程序时重建。然而,我的应用程序在没有 notifyListeners 的情况下运行良好,因为 sharedPreferencesData 包含只会在应用程序运行和登录时更新的变量。所以我再次陷入困境,如何解决这个问题。 我认为你应该用你的notifyListeners
来解决这个问题。该错误告诉我您在 build
方法中调用了 notifyListeners
是错误的。
嗨 Shahin,我已经使用 WidgetsBinding.instance.addPostFrameCallback 解决了我的 notifyListeners 问题。现在 sharedPreferencesData 应该通知侦听器,因此会更新以通知代理提供者.. 我做了以下事情:
ChangeNotifierProvider.value(value: SharedPreferencesData(), ), ProxyProvider以上是关于Flutter:在 Stream 类中访问 SharedPreferences Provider / ChangeNotifier的主要内容,如果未能解决你的问题,请参考以下文章
如何访问和更改在 FLUTTER/DART 的另一个类中声明的字符串变量的值
Flutter - 获取 SHA-1 证书 - Android Studio 3.2.1