Flutter 如何设置从另一个StreamProvider获取参数值的StreamProvider?

Flutter 如何设置从另一个StreamProvider获取参数值的StreamProvider?,flutter,flutter-provider,Flutter,Flutter Provider,我正在为我的应用程序使用FirebaseAuth和Firestore “用户”是一个模型,表示firestore上的文档,并使用FirebaseUser的uid作为其文档ID 为了获得“用户”,我必须从FirebaseUser传入uid 我的想法是设置FirebaseUser的StreamProvider,然后设置另一个User的StreamProvider,它将FirebaseUser作为参数 但是出现了错误,我找不到解决这个问题的方法,任何建议都会对我很有帮助 List<SingleC

我正在为我的应用程序使用FirebaseAuth和Firestore

“用户”是一个模型,表示firestore上的文档,并使用FirebaseUser的uid作为其文档ID

为了获得“用户”,我必须从FirebaseUser传入uid

我的想法是设置FirebaseUser的StreamProvider,然后设置另一个User的StreamProvider,它将FirebaseUser作为参数

但是出现了错误,我找不到解决这个问题的方法,任何建议都会对我很有帮助

List<SingleChildCloneableWidget> uiConsumableProviders = [
  StreamProvider<FirebaseUser>(
    builder: (context) => Provider.of<LoginNotifier>(context, listen: false).streamFirebaseUser,
  ),
  StreamProvider<User>(
    builder: (context) =>
        Provider.of<UserNotifier>(context, listen: false).streamUser(Provider.of<FirebaseUser>(context)),
  ),
];
列出uiConsumableProviders=[
流提供者(
builder:(context)=>Provider.of(context,listen:false).streamFirebaseUser,
),
流提供者(
生成器:(上下文)=>
Provider.of(context,listen:false).streamUser(Provider.of(context)),
),
];
I/颤振(15813):══╡ WIDGETS库捕获到异常╞═══════════════════════════════════════════════════════════
I/flatter(15813):在生成InheritedProvider时抛出以下断言:
I/flatter(15813):调用了inheritFromWidgetOfExactType(InheritedProvider)或inheritFromElement()
I/flatter(15813):在BuilderStateDelegate.initDelegate()完成之前。
I/颤振(15813):
I/flatter(15813):当继承的小部件发生变化时,例如如果Theme.of()的值
I/flatter(15813):更改,重建其依赖的小部件。如果依赖小部件的引用
I/flatter(15813):如果继承的小部件位于构造函数或initDelegate()方法中,则
I/flatter(15813):重建的依赖小部件将不会反映继承小部件中的更改
I/flatter(15813):小部件。
I/颤振(15813):
I/flatter(15813):通常,对继承小部件的引用应该出现在小部件构建()中
I/颤振(15813):方法。或者,可以放置基于继承小部件的初始化
I/flatter(15813):在didChangeDependencies方法中,在initDelegate和
I/flatter(15813):此后依赖项发生变化时。
I/颤振(15813):

您不能在
builder
内部调用
Provider.of

但您可以使用小部件将
Provider.of
转换为流,然后在
StreamProvider
builder
中使用该流

这里有一个小部件可以为您实现这一点:

类ProviderToStream扩展StatefulWidget
实现SingleChildCloneableWidget{
const ProviderToStream({Key-Key,this.builder,this.child}):super(Key:Key);
最终价值:建筑商;
最后一个孩子;
@凌驾
_ProviderToStreamState createState()=>\u ProviderToStreamState();
@凌驾
ProviderToStream cloneWithChild(小部件子项){
返回ProviderToStream(
钥匙:钥匙,
建筑商:建筑商,
孩子:孩子,
);
}
}
类_ProviderToStreamState扩展状态{
最终StreamController=StreamController();
@凌驾
无效处置(){
controller.close();
super.dispose();
}
@凌驾
void didChangeDependencies(){
super.didChangeDependencies();
controller.add(Provider.of(context));
}
@凌驾
小部件构建(构建上下文){
返回widget.builder(context、controller.stream、widget.child);
}
}
然后你可以做:

MultiProvider(
供应商:[
StreamProvider(生成器:(\u)=>Stream.empty()),
ProviderToStream(
生成器:(uo,foo,child)=>StreamProvider(
生成器:(_)异步*{
等待(foo中的最终值){
屈服值。toString();
}
},
孩子:孩子,
),
),
],
子项:MaterialApp(),
);

经过一些变通之后,我通过将
rxdart
中的
可观察的
提供者
相结合,解决了我的问题。像这样:

Stream<User> get userStream {
return Observable(_firebaseAuth.onAuthStateChanged).switchMap((user) {
  if (user != null) {
    return userCollection
        .document(user.uid)
        .snapshots()
        .map((doc) => User.fromDocumentSnapshot(doc))
        .handleError(_catchError);
  } else {
    return Observable<User>.just(null);
  }
});}
Stream获取用户流{
返回可观察(_firebaseAuth.onAuthStateChanged)。开关映射((用户){
如果(用户!=null){
返回用户集合
.document(user.uid)
.快照()
.map((doc)=>User.fromDocumentSnapshot(doc))
.handleError(_catchError);
}否则{
返回可观察值。just(null);
}
});}
外部多供应商:

StreamProvider<User>(builder: (context) => Provider.of<FireStoreService>(context, listen: false).userStream,),
StreamProvider(builder:(context)=>Provider.of(context,listen:false).userStream,),

希望这能帮助任何面临同样问题的人。

目前还不支持。现在还不清楚它是如何工作的,因为
builder
只被调用一次,但是从另一个提供程序获得的值可以随着时间的推移而改变。@RémiRousselet是的,这正是我被卡住的原因。我的目的是想从widget树的任何地方获取用户数据,所以我需要流之类的东西。你能给我一些关于这个问题的建议吗?嗨,雷米,如果我只是想做这个:多提供者(提供者:[StreamProvider.value(value:AppAuth.currentUser),StreamProvider.value(value:AppDb.getUserData(Provider.of(context)?.uid),],但是UserDataModel首先需要来自AuthUser的uid的输入?需要包含哪些包才能工作?我得到了对SingleChildCloneableWidget的未解析引用
StreamProvider<User>(builder: (context) => Provider.of<FireStoreService>(context, listen: false).userStream,),