有状态小部件消费者小部件构建两次,因此调用 initState 两次。如何阻止这种情况发生?

发布于 2025-01-16 06:38:57 字数 1814 浏览 3 评论 0原文

因此,对于我的项目,我正在使用 Riverpod,并且正在创建应用程序的主页。 这棵树看起来像这样 ->

CommunityView(Stateful Widget)
WillPopScope
ProviderScope
Consumer
Scaffold
...and so on

现在,在 CommunityView 小部件的构建方法中,

 final params = _VSControllerParams(
      selectedFamily: widget.selectedFamily,
    );
    print('familiesStatus: rebuild main');

    return WillPopScope(
      onWillPop: onWillPop,
      child: ProviderScope(
        overrides: [_paramsProvider.overrideWithValue(params)],
        child: Consumer(
          builder: (context, watch, child) {
            print('familiesStatus: rebuild consumer');
            final state = watch(_vsProvider(params));
            final stateController = watch(_vsProvider(params).notifier);

rebuild main 打印仅发生一次,而 rebuild Consumer 打印发生两次。以前的主页获取数据,然后根据网络响应显示获取的数据或错误。现在我使用枚举来获取加载状态,即 ApiStatus.loading 是初始状态,然后 ApiStatus.success 或失败取决于响应。现在我所做的导致此问题的更改是 ->我在 initstate 中添加了一个函数调用,用于获取本地保存的缓存并从中加载数据。那么会发生什么情况是 ApiStatus.loading->ApiStatus.success(已获取缓存)->ApiStatus.loading(以某种方式重建整个小部件)->ApiStatus.success(再次获取缓存)->ApiStatus.success(从互联网)。所以我不确定为什么在获取缓存时第一次重建。

现在为了解决这个问题,我首先尝试在缓存方法调用中查找导致此重建的任何原因,但即使进行大量调试也无法找到任何原因。然后我想创建一个像这样的全局参数

bool fetchDataFromCache = true;

,然后在 initState 内部,我调用像这样的 fetch Cache 方法

if(fetchDataFromCache){
    fetchCache();
    fetchDataFromCache = false;
}

但这导致 ApiStatus 加载参数像这样改变 ->ApiStatus.loading(initial build)-> ApiStatus.success(已获取缓存)->ApiStatus.loading(以某种方式重建整个小部件)->ApiStatus.success(从互联网获取数据)。所以小部件仍在重建,因为我只在 initState 中设置了 ApiStatus.loading,而没有在其他地方设置。所以还是出问题了。

演示视频 - https://youtu.be/1EzYfCRiwk0

So for my project, I am using Riverpod, and I am creating the home page of my app.
The tree looks like this ->

CommunityView(Stateful Widget)
WillPopScope
ProviderScope
Consumer
Scaffold
...and so on

Now inside the build method of the CommunityView Widget,

 final params = _VSControllerParams(
      selectedFamily: widget.selectedFamily,
    );
    print('familiesStatus: rebuild main');

    return WillPopScope(
      onWillPop: onWillPop,
      child: ProviderScope(
        overrides: [_paramsProvider.overrideWithValue(params)],
        child: Consumer(
          builder: (context, watch, child) {
            print('familiesStatus: rebuild consumer');
            final state = watch(_vsProvider(params));
            final stateController = watch(_vsProvider(params).notifier);

The rebuild main print happens only once, while the rebuild consumer print happens twice. Previously home page fetched data and then shows data fetched or error depending on network response. Now I use an enum to get loading state, i.e. ApiStatus.loading is the initial state, then ApiStatus.success or failure depending on response. Now what I have changed that is causing this issue is -> I have added a function call in initstate that fetches local saved cache and loads data from that. So what happens is ApiStatus.loading->ApiStatus.success(Cache fetched)->ApiStatus.loading(somehow whole widget rebuild)->ApiStatus.success(cache fetched again)->ApiStatus.success(Data fetched from internet). So I am not sure why it is rebuilding first time when cache is fetched.

Now to fix this, I first tried to find any reason in the cache method call that is causing this rebuild, but was not able to find any even with heavy debugging. Then I thought to create a global parameter which is something like this

bool fetchDataFromCache = true;

and then inside initState, I call fetch Cache method something like this

if(fetchDataFromCache){
    fetchCache();
    fetchDataFromCache = false;
}

But this caused the ApiStatus loading parameter to change like this ->ApiStatus.loading(initial build)->ApiStatus.success(Cache fetched)->ApiStatus.loading(somehow whole widget rebuild)->ApiStatus.success(Data fetched from internet). So widget is still rebuilding because I have set ApiStatus.loading only in initState, and nowhere else. So it is still glitching out.

Demo video - https://youtu.be/1EzYfCRiwk0

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文