You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中使用Provider实现每个Tab页独立Data实例的方案

解决方案

问题根源在于所有Tab页共享了同一个全局的Data实例,所以点击计数按钮时所有页面的计数器会同步更新。要实现每个Tab页拥有独立的计数器,需要为每个Tab对应的页面单独创建Data实例,具体实现如下:

修改后的完整代码

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    // 移除全局的ChangeNotifierProvider,改为在每个Tab页面单独创建
    return MaterialApp(
      title: _title,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  // 模拟动态获取的类别列表(实际场景可从接口或其他来源获取)
  final List<String> categories = ['People', 'Cars', 'Animals'];

  List<Tab> getTabs() {
    return categories.map((category) => Tab(text: category)).toList();
  }

  @override
  Widget build(BuildContext context) {
    final tabs = getTabs();
    return DefaultTabController(
      length: tabs.length,
      child: Scaffold(
        appBar: AppBar(
          bottom: TabBar(tabs: tabs),
        ),
        body: TabBarView(
          children: tabs.map((Tab tab) {
            // 为每个Tab页面单独包裹ChangeNotifierProvider,创建独立的Data实例
            return ChangeNotifierProvider<Data>(
              create: (_) => Data(),
              child: CategoryTabPage(categoryName: tab.text!),
            );
          }).toList(),
        ),
      ),
    );
  }
}

// 抽离Tab页面为单独组件,便于维护和复用
class CategoryTabPage extends StatelessWidget {
  final String categoryName;

  const CategoryTabPage({super.key, required this.categoryName});

  @override
  Widget build(BuildContext context) {
    // 使用Consumer监听当前页面的Data变化,避免不必要的重建
    return Consumer<Data>(
      builder: (context, data, child) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              categoryName,
              style: Theme.of(context).textTheme.headline5,
            ),
            const SizedBox(height: 30),
            Text(
              data.counter.toString(),
              style: Theme.of(context).textTheme.headline3,
            ),
            const SizedBox(height: 30),
            ElevatedButton(
              onPressed: data.increment,
              child: const Text('Count'),
            ),
          ],
        );
      },
    );
  }
}

class Data extends ChangeNotifier {
  int counter = 0;

  void increment() {
    counter++;
    notifyListeners();
  }
}

核心改动说明

  • 移除全局Provider:不再在MyApp中提供全局的Data实例,避免所有页面共享同一个状态。
  • 为每个Tab单独创建Provider:在TabBarView的每个子项外层包裹ChangeNotifierProvider,每个Provider都会创建新的Data实例,保证每个Tab的状态独立。
  • 抽离Tab页面组件:将Tab内容封装为CategoryTabPage,通过Consumer监听当前页面的Data变化,确保只有当前页面会响应状态更新。

这种方案完全适配类别预先未知的场景,只需要动态传入类别列表,就能自动为每个类别创建独立的Tab和对应的状态实例。

内容的提问来源于stack exchange,提问作者Niels

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 13:50:25