如何从父小部件在子状态小部件内运行函数? [英] How to run a function inside a child stateful widget from parent widget?

查看:137
本文介绍了如何从父小部件在子状态小部件内运行函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过在该孩子的父母的父母中点击按钮在StateFul小部件内的两层内运行该函数(带有自变量)( 构建完所有小部件之后,而不是在构造函数之内)。就像下面的图片一样:



更多细节是我创建了Carousal里面有卡片,



在首页屏幕内:

  ///。 ..Inside Homepage屏幕级别0 
RaisedButton(
子级:Text('BLoC中的更新值'),
onPressed:(){
bloc.changeSelectedState(isSel) ;
},
),
// ...

在BLoC内部:

 类Bloc {
最终的BehaviorSubject< bool> _isSelectedStreamController = BehaviorSubject< bool>();

//从流
中检索数据Stream< bool>得到isSelectedStream => _isSelectedStreamController.stream;

//将数据添加到流
Function(bool)get changeSelectedState => _isSelectedStreamController.sink.add;

void dispose(){
_isSelectedStreamController.close();
}
}
final bloc = Bloc();

在任何级别的任何小部件内,只要它可以到达整个集团即可:

  //这在两级向下的有状态小部件内。.
StreamSubscription isSelectedSubscription;
Stream isSelectedStream = bloc.isSelectedStream;
isSelectedSubscription = isSelectedStream.listen((value){
//设置标志,然后设置setState以便显示边框。
setState((){
isSelected = value;
});
});

// ...其他代码

@override
Widget build(BuildContext context){

return Container(
装饰:isSelected
?BoxDecoration(
颜色:Colors.deepOrangeAccent,
边框:Border.all(
宽度:2,
颜色:Colors.amber,
),

:null,
// ...其他代码
);
}

所以我小部件的新设计将BLoC作为主要内容





and ...以灵活,简洁的代码和体系结构像魅力一样工作^^


I am trying to run a function(with arguments) inside two-levels down StateFul widget, by clicking a button in the parent of the parent of that child(after having all widgets built, so not inside the constructor). just like in the image below:

More details is that I created a Carousal which has Cards inside, published here.

I created it with StreamBuilder in mind(this was the only use case scenario that I used it for so far), so once the stream send an update, the builder re-create the whole Carousal, so I can pass the SELECTED_CARD_ID to it.

But now I need to trigger the selection of the carousal's Cards programmatically, or in another word no need for two construction based on the snapshot's data like this:

return StreamBuilder(
      stream: userProfileBloc.userFaviourateStream,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return SelectableCarousal(
            selectedId: snapshot.data.toInt(),
            onTap: //Update the stream
            //some props...,
          );
        } else {
          return SelectableCarousalLoading(
            selectedId: null,
            onTap: //Update the stream
            //some props...,
          );
        }
      },
    );

But instead, I'm trying to have something like this so I can use it for others use cases:

Widget myCarousal =  SelectableCarousal(
    selectedId: null,
    onTap: //Update the stream
    //some props...,
);
return StreamBuilder(
      stream: userProfileBloc.userFaviourateStream,
      builder: (context, snapshot) {

        // Then when data ready I can update 
        // the selection by calling two-level down function
        if (snapshot.hasData) {
          myCarousal.selectById(3);
        }

        // Build same carousal in all cases.
        return myCarousal;
      },
    );

so this led me to my original question "How to run a function(with arguments) inside two-levels down StateFul widget?".

I appreciate any help. thanks a lot.

解决方案

I was able to solve that challenge using the BLoC & Stream & StreamSubscription, see the image below:

Inside the Homepage screen:

///...Inside Homepage screen level-0
RaisedButton(
    child: Text('Update value in the BLoC'),
    onPressed: () {
         bloc.changeSelectedState(isSel);
    },
),
//...

inside the BLoC:

class Bloc {
  final BehaviorSubject<bool> _isSelectedStreamController = BehaviorSubject<bool>();

  // Retrieve data from stream
  Stream<bool> get isSelectedStream => _isSelectedStreamController.stream;

  // Add data to stream
  Function(bool) get changeSelectedState => _isSelectedStreamController.sink.add;

  void dispose() {
    _isSelectedStreamController.close();
  }
}
final bloc = Bloc();

Inside any widget in any level as long as it can reach the bloc:

// This inside the two-levels down stateful widget..
StreamSubscription isSelectedSubscription;
Stream isSelectedStream = bloc.isSelectedStream;
isSelectedSubscription = isSelectedStream.listen((value) {
      // Set flag then setState so can show the border.
      setState(() {
        isSelected = value;
      });
});

//...other code

@override
Widget build(BuildContext context) {

   return Container(
      decoration: isSelected
          ? BoxDecoration(
              color: Colors.deepOrangeAccent,
              border: Border.all(
                width: 2,
                color: Colors.amber,
              ),
            )
          : null,
          //...other code
    );
}

so the new design of my widget includes the BLoC as a main part of it, see the image:

and...works like a charm with flexible and clean code and architecture ^^

这篇关于如何从父小部件在子状态小部件内运行函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆