dart 我可以在没有外部状态管理库的情况下触发祖父状态更改吗?

13z8s7eq  于 2023-01-15  发布在  其他
关注(0)|答案(2)|浏览(128)

我找不到一个令人满意的方法来触发孙子部件的祖父状态变化。我的应用程序保存和来源的数据都来自一个设备上的数据库。我试图进行这么远没有使用状态管理库,因为我认为这是矫枉过正-应用程序并不复杂。
我有一个ListView(grandparent),它又有我自己的ListTiles版本的子项。每个ListTile上有两个图标按钮,一个用于编辑,一个用于删除-这两个按钮都触发不同的alertdialog(孙)弹出窗口。当我对数据执行更新或删除时,它被写入数据库并返回Future-然后我需要祖父ListView状态来刷新。StatefulBuilders只给予刷新孙节点状态的方法(与子对象分开),而不是触发“多级别”状态更改的方法。
是时候采用BLOC或Riverpod等状态管理解决方案了,还是有其他解决方案?

ListView祖父级小部件

@override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Builder(
          builder: (BuildContext context) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                // other children here
                Expanded(
                  flex: 11,
                  child: FutureBuilder<List<MyCustomObject>>(
                  future: _getQuotes(), // queries the db
                  builder: (context, AsyncSnapshot snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting
                        && !snapshot.hasData) {
                      return const Center(
                        child: SizedBox(
                          height: AppDims.smallSizedBoxLoadingProgress,
                          width: AppDims.smallSizedBoxLoadingProgress,
                          child: CircularProgressIndicator()
                        ),
                      );
                    } else if (snapshot.hasError) {
                      log(snapshot.error.toString());
                      log(snapshot.stackTrace.toString());
                      return Center(child: Text(snapshot.error.toString()));
                    } else {
                        // no point using StatefulBuilder here, as i need 
                        // to potentially trigger _getQuotes() again to rebuild the entire ListView
                      return ListView.builder(
                        padding: const EdgeInsets.symmetric(
                          horizontal: AppDims.textHorizontalPadding,
                          vertical: AppDims.textVerticalPadding
                        ),
                        itemCount: snapshot.data!.length,
                        itemBuilder: (context, int index) {
                          return MyCustomTile(
                            // tile data mapping from snapshot for MyCustomObject
                          );
                        },
                      );
                    }
                  },
                )
              )
            ]
          );
        }
      )
    );
  }

MyCustomTile子部件

@override
  Widget build(BuildContext context) {
    return Card(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(AppDims.tileBorderRadius),
        side: const BorderSide(
          color: Colors.green,
          width: 1.5,
        )
      ),
      child: ListTile(
        // other omitted ListTile params here
        trailing: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisSize: MainAxisSize.min,
          children: [
            IconButton(
              icon: const Icon(Icons.edit),
              onPressed: () => showDialog(
                context: context,
                barrierDismissible: true,
                builder: (BuildContext context) {
                  return EditDialog();
                }
              ).then((_) => setState(() {})), // will only setState on the dialog!
            ),
            IconButton(
              icon: const Icon(Icons.delete),
              onPressed: () => showDialog(
                context: context,
                barrierDismissible: true,
                builder: (BuildContext context) => DeleteWarningDialog(
                  widget.id,
                  AppStrings.price.toLowerCase(),
                  true
                ),
              ),
            ),
          ]
        ),
      ),
    );
  }

DeleteWarningDialog孙小部件

@override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text(_buildFinalWarningString()),
      actions: [
        TextButton(
          child: const Text(AppStrings.cancel),
          onPressed: () => Navigator.pop(context),
        ),
        TextButton(
          child: const Text(AppStrings.delete),
          onPressed: () {
            _appDatabase.deleteFoo(widget.objectIdToDelete);
            Navigator.pop(context);
          },
        )
      ],
    );
  }
whlutmcx

whlutmcx1#

您可以创建一个更新祖父小部件的state的函数,并将其从祖父传递到父,然后从父传递到孙,并在您想要更新祖父widget的任何地方使用它

arknldoa

arknldoa2#

你必须在grandParent中声明一个函数,在你的例子中就是listView,然后把它传递给parent和children。但是这会很复杂,效率也不高,使用状态管理会使它变得简单和干净

相关问题