将变量从 MaterialPageRoute 传递到自定义小部件

Posted

技术标签:

【中文标题】将变量从 MaterialPageRoute 传递到自定义小部件【英文标题】:Pass variable from MaterialPageRoute to custom widget 【发布时间】:2021-10-10 22:29:55 【问题描述】:

一点背景知识:Flutter noob here,试图构建一个添加到收藏夹功能。项目列表位于我在 FirstScreen 上使用 http 访问的 php/mysql 数据库中。当用户点击其中一个列表项时,他们会被重定向到 SecondScreen,我使用 MaterialPageRoute 传递“itemId”,它有一个“添加到收藏夹”按钮。收藏项目的“itemId”使用 sqflite 存储在本地。我可以使用 StatefulWidget 访问“itemId”,但我没有成功尝试创建管理无状态小部件的自定义 Stateful 小部件,就像在这个 Flutter example on interactivity 中一样,即我无法从自定义 Stateful 小部件访问“itemId” .

代码sn-p:

MaterialPageRoute(
  builder: (context) => SecondScreen(
  itemId: item[index].itemId,

我的 sqflite checkFavourited 函数:

Future<bool> checkFavourited(String itemId) async 
        Database db = await instance.database;
        var bookmarked = await db.query(table,
            where: 'itemId = ?',
            whereArgs: [itemId]);
        return bookmarked.isEmpty ? false : true;
      

工作状态小部件:

 bool _isFavourited = false;

  void isFavourited() async 
    final isFavourited =
        await DatabaseHelper.instance.checkFavourited(widget.itemId);
    setState(() 
      _isFavourited = isFavourited;
    );
  

但我在 StatelessWidget 中的尝试失败了。到目前为止,我有:

class SecondScreen extends StatelessWidget 
  final String itemId;
  SecondScreen(
    Key key,
    @required this.itemId,

我收到以下错误消息:

The getter 'itemId' isn't defined for the type 'FavouritedButton'.

当我尝试这样做时:

class FavouritedButton extends StatefulWidget 
  @override
  _FavouritedButtonState createState() => _FavouritedButtonState();


class _FavouritedButtonState extends State<FavouritedButton> 
  bool _isFavourited = false;

  void isFavourited() async 
    final isFavourited =
    await DatabaseHelper.instance.checkBookmark(widget.itemId);
    setState(() 
      _isFavourited = isFavourited;
    );
  
  @override
  Widget build(BuildContext context) 
    return IconButton(
      icon: isFavourited
          ? Icon(Icons.bookmark)
          : Icon(
              Icons.bookmark_border,
            ),

我已阅读 Flutter's Simple app state management 和 List of state management approaches 的文章,我可能错了,但有没有比 Provider 或 FutureBuilder 更简单的解决方案?

我知道这是一篇很长的帖子,如果有人能就此给予我一些指示,我将不胜感激。提前致谢!

【问题讨论】:

【参考方案1】:

根据您的代码 sn-p,您正在使用 Construstor 传递数据。但是您没有在FavouritedButton 中声明itemId。正如@Huthaifa Muayyad 所说,它将得到解决。如果你喜欢将数据作为路由参数传递,你需要像这样传递

  Navigator.of(context).push(
                  MaterialPageRoute(
                      builder: (context) => FavouritedButton (),
                      settings: RouteSettings(
                        arguments: itemId,
                      )),
                );

在 widgetSide 上接收

 Widget build(BuildContext context) 
    final data = ModalRoute.of(context)!.settings;

我描述更多here

【讨论】:

【参考方案2】:

干净的代码方法,通过将您的小部件重建隔离为尽可能窄,您正在做正确的事情,但需要将 id 移动到您的有状态小部件。

class FavouritedButton extends StatefulWidget 
final String itemId;
  FavouritedButton(required this.itemId);

  @override
  _FavouritedButtonState createState() => _FavouritedButtonState();

class _FavouritedButtonState extends State<FavouritedButton> 
//add initState here, and keep the rest of your widget as it is.
 @override
  void initState() 
  isFavourited();
    super.initState();
  

然后在你的无状态小部件中:

class SecondScreen extends StatelessWidget 
 final String itemId;

  const SecondScreen(Key? key, required this.itemId) : super(key: key);

  @override
  Widget build(BuildContext context) 
    
    return Column(children:[
     Text('write some text about your widget or $itemId'),
     FavouritedButton(itemId:itemId)
  ]);
  

这只会重建你最喜欢的按钮。

【讨论】:

工作就像一个魅力!两个问题:我在 initState 和 Key key 之后添加了一个 dispose 函数:StatefulWidget 中所需的 'itemId' 的 super(key: key) ,它们有必要吗? 键只有在您使用时才好用,它们不是必需的,但首选,因为您的小部件变得更加复杂,键将提高性能。至于 dispose,它在被移除时已经内置在小部件中,例如 initstate,但是如果您没有在 dispose 中添加任何逻辑,则无需编写,并且在您的小部件中,您没有任何要处置的东西流或侦听器或焦点节点。

以上是关于将变量从 MaterialPageRoute 传递到自定义小部件的主要内容,如果未能解决你的问题,请参考以下文章

Flutter MaterialPageRoute 导航到黑色背景的屏幕时如何解决?

在 Flutter 的屏幕之间传递 Hive 框

我想导航到另一个页面并使用 Firestore 数据进行解析,但是当我使用 MaterialPageRoute 时该怎么做?

如何将变量从变量传递给指针结构对象?

将变量从 Powershell 脚本传递到 SQLPlus

将变量从厨师传递到PowerShell