颤振回调到后退按钮上的原始小部件

Posted

技术标签:

【中文标题】颤振回调到后退按钮上的原始小部件【英文标题】:Flutter call back to originating widget on back button 【发布时间】:2018-07-16 15:03:33 【问题描述】:

我有一个构建 ListView.builder 的 Future Builder,构建器 ListTiles 由另一个具有 ontap 功能的小部件构建。我已经弄清楚如何使用后退按钮在最终的小部件上运行某些东西,但无法弄清楚如何在后退按钮上的原始小部件上调用某些东西。例如,当用户单击后退按钮时,我需要刷新***数据,而不仅仅是已经工作的辅助小部件中的数据。

我希望这是有道理的,任何帮助都会很棒。

更新这是代码。我正在简化我所展示的内容,因为做一个简单的例子会失去上下文。下面你会看到我有一个 FutureBuilder,它返回一个 ListBuilder,它返回一个新的 ChatWidget。这是顶层,当我点击后退按钮时,这个 Future 需要刷新。然而,捕获回调的 onTap 在 ChatWidget 中。

new Expanded(
      child: new RefreshIndicator(
          child: new FutureBuilder<List<Map>>(
              future: chatlist,
              builder: (BuildContext context, AsyncSnapshot<List<Map>> snapshot) 
                switch (snapshot.connectionState) 
                  case ConnectionState.none: return new Text('Waiting to start');
                  case ConnectionState.waiting: return new Text('Loading...');
                  default:
                    if (snapshot.hasError) 
                      return new Text('Error: $snapshot.error');
                     else 
                      return new ListView.builder(
                        itemBuilder: (context, index) 
                          ChatServerList mychat = new ChatServerList(snapshot.data[index]['msgkey'],snapshot.data[index]['refid'],snapshot.data[index]['referralname'], snapshot.data[index]['oid'],snapshot.data[index]['sendname'],snapshot.data[index]['pid'],snapshot.data[index]['receivename'],snapshot.data[index]['pgrpid'],snapshot.data[index]['prid'],snapshot.data[index]['message'],);
                          bool isgroup = true;
                          if (mychat.grpid == 0) 
                            isgroup = false;
                          
                          return new ChatWidget(mychat: mychat,threaded: threaded, isgroup: isgroup);
                        ,
                        itemCount: snapshot.data.length,
                      );
                    
                
              ,
          ),
          onRefresh: _onRefresh
      ),
  )

这是在 ChatWidget 中构建的,您会注意到 _onTap:

new MyListTile(
              leading: new CircleAvatar(
                child: _chatAvatar(),
                //child: !isgroup ? _indMsg() : _grpMsg(), radius: 18.0,
              ),
              //subtitle: new Text(widget.mychat.oname),
              title: new Text(widget.mychat.referralname),
              trailing: new Text(widget.mychat.oname, textAlign: TextAlign.right,),
              //isThreeLine: true,
              //onTap: doTap(threaded),
              onTap: _onTap,
              onLongPress: _doArchive,
            ),
            new MyListTile(
              leading: new Text('        '),
              title: new Text(submymessage, textAlign: TextAlign.left,
                style: new TextStyle(fontSize: 15.0,
                    color: Colors.grey, fontStyle: FontStyle.italic),),
              trailing: _unreadBabdge(),
              onTap: _onTap,
              onLongPress: _doArchive,
            ),

_onTap 在下面,并且有处理后退按钮的代码。

_onTap() async 
    ChatDB.instance.updateRead(widget.mychat.msgkey);
    if (threaded) 
      //TODO
     else 
      Route route = new MaterialPageRoute(
        settings: new RouteSettings(name: "/ChatServerDivided"),
        builder: (BuildContext context) => new ChatServerDivided(mychat: widget.mychat, title: "Chat Messages",),
      );
      //Navigator.of(context).push(route);
      var nav = await Navigator.of(context).push(route);
      if(nav==true||nav==null)
        unread = ChatDB.instance.getUnread(widget.mychat.msgkey);
      
    


  

所以我想要找到的是,如果这段代码可以以某种方式与原始小部件通信,以便我可以再次运行原始的 Future。我希望这更有意义,更容易理解。

【问题讨论】:

没有例子这真的很混乱吗? 添加了代码。这是您之前帮助我处理的同一页面,但现在我需要在同一背面刷新顶部的数据,并且不知道如何一直调用回原来的 Future。 我并不是要发布完整的代码,我仍然对您的问题感到困惑。也许只是添加一个你想要实现的简化案例,一个关于虚拟数据的较小实验,以便任何人都可以轻松地遵循。 如果您查看此项目,您帮助我处理了 ***.com/questions/48582963/… 它适用于具有路由的小部件(我的代码中的 ChatServerList),但是我需要顶层也刷新我的代码是 ChatServerPage 小部件。不知道如何让***小部件在同一个后退按钮单击时刷新 您能否自定义链接中的示例以显示您的意思?对我来说让它更简单,因为浏览整个代码会很麻烦。只需创建一个虚拟示例来复制您的问题,以便我可以跟进。 【参考方案1】:

是的,您可以这样做。无法确切看到将其放入您的代码的确切位置,但我会为您提供处理此问题的方法。导航器调用都是期货,这意味着您可以在调用方等待它们。似乎您只是缺少将值传递给 .pop 调用。下面是一个例子。

您可以在哪里导航,等待结果

var navigationResult = await Navigator.push(
        context,
        new MaterialPageRoute(
            builder: (context) => Page2()));

然后你可以用一个简单的if来检查navigationResult。

if(navigationResult == 'rerun_future') 
    uploadFiles(); // Perform your custom functionality here.
 

您将这些信息传回的方式是,当您执行 pop 调用(导航返回)时,您将在其中传递值 'rerun_future'。

Navigator.of(context).pop('rerun_future') 

此外,如果您还想将此功能添加到后退按钮,您应该使用 WillPopScope 围绕您的 Scaffold,返回 false 给 onWillPop 并为您执行自定义弹出调用的 appBar 提供一个前导项。以下示例来自this post

@override
Widget build(BuildContext context) 
  return new WillPopScope(
    onWillPop: () async => false,
    child: new Scaffold(
      appBar: new AppBar(
        title: new Text("data"),
        leading: new IconButton(
          icon: new Icon(Icons.ac_unit),
          onPressed: () => Navigator.of(context).pop('rerun_future'), //<----- pass value here too
        ),
      ),
    ),
  );

【讨论】:

以上是关于颤振回调到后退按钮上的原始小部件的主要内容,如果未能解决你的问题,请参考以下文章

颤振:单击该小部件内的按钮后如何将小部件更改为另一个小部件

我应该使用啥颤振小部件? (向左滑动一页)

Wheel ListView 小部件内的颤振按钮

颤振错误:此小部件已卸载,因此状态不再具有上下文(应视为已失效)

提取的小部件内的颤振滑块

颤振:如何更新文本小部件值