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

Flutter跨组件TabBarView setState刷新及SharedPreferences数据加载问题

解决Flutter Todo应用TabBarView页面刷新问题

问题核心

  1. pendingList仅在initState阶段加载一次数据,新增任务后不会自动重新获取数据更新UI
  2. MainApp中的setState()只能刷新自身组件,无法触发TabBarView内子组件的数据重载

解决方案:通过GlobalKey触发子组件刷新

步骤1:修改pendinglist.dart,暴露刷新方法

给pendingList添加GlobalKey,并新增刷新方法让父组件可以调用:

import 'package:flutter/material.dart';
import 'package:casestudy/db_file.dart';

// 定义GlobalKey,用于父组件访问子组件状态
final GlobalKey<_pendingListState> pendingListKey = GlobalKey<_pendingListState>();

class pendingList extends StatefulWidget {
  const pendingList({Key? key}) : super(key: key);

  @override
  State<pendingList> createState() => _pendingListState();
}

class _pendingListState extends State<pendingList>{
  var db;
  late List data = [];
  
  @override
  void initState() {
    super.initState();
    loadData();
  }
  
  @override
  Widget build(BuildContext context) {
    return returnBuildContent();
  }
  
  Widget returnBuildContent(){
    print("pendingList Buildmethod function called");
    if(data.length == 0){
      return Scaffold(
        body: SingleChildScrollView(
          child: Center(
            child: Column(
              children: [
                Image.asset('assets/images/noDataFound2.png'),
                Text("No Task are present now!",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.greenAccent),)
              ],
            ),
          ),
        ),
      );
    }else{
      return Padding(
          padding: const EdgeInsets.all(8.0),
          child: ListView.builder(
              itemCount: data.length,
              itemBuilder: (BuildContext context, int index){
                var dt = data[index];
                return Card(
                  child: Row(
                    children: [
                      Expanded(child: Padding(
                        padding: EdgeInsets.only(top: 10,bottom: 10,left: 15),
                        child: Text(dt['description']),
                      )),
                      IconButton(
                          onPressed: (){},
                          icon: Icon(Icons.edit_rounded)
                      ),
                      IconButton(
                          onPressed: (){},
                          icon: Icon(Icons.check_circle_rounded)
                      ),
                    ],
                  ));
              }
          ),
      );
    }
  }

  loadData()async{
    db = await db_file();
    data = db.getData();
    List highPriorityData = [], intermediatePriorityData = [], lowPriorityData = [];
    for(int i=0;i<data.length;i++){
      if(data[i]['priority'] == "Top"){
        highPriorityData.add(data[i]);
      }else if(data[i]['priority'] == "Intermediate"){
        intermediatePriorityData.add(data[i]);
      }else if(data[i]['priority'] == "Low"){
        lowPriorityData.add(data[i]);
      }
    }
    data = [];
    if(highPriorityData.length != 0){
      data.addAll(highPriorityData);
    }
    if(intermediatePriorityData.length != 0){
      data.addAll(intermediatePriorityData);
    }
    if(lowPriorityData.length != 0){
      data.addAll(lowPriorityData);
    }
    setState(() {});
  }

  // 新增:暴露给父组件的刷新方法
  void refreshData() {
    loadData();
  }
}

步骤2:修改main.dart,调用子组件刷新方法

在MainApp中使用GlobalKey关联pendingList,并在保存数据后直接触发刷新:

import 'package:casestudy/db_file.dart';
import 'package:flutter/material.dart';
import 'package:casestudy/pendinglist.dart';
import 'package:casestudy/completedlist.dart';

void main() {
  runApp(MaterialApp(debugShowCheckedModeBanner: false,theme: ThemeData.dark(),home:MainApp()));
}

class MainApp extends StatefulWidget {
  const MainApp({super.key});

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> with TickerProviderStateMixin  {
  TextEditingController todoDescription = TextEditingController();
  late TabController _tabController;
  var db,data;
  String dropdownValue = "Top";
  @override
  initState() {
    super.initState();
    db = db_file();
    _tabController = TabController(length: 2, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    print("build method is called");
    return Scaffold(
        appBar: AppBar(
            title: const Text("Todo Application"),
            bottom: TabBar(
              tabs: [
                Tab(text: "Pending"),
                Tab(text: "Completed"),
              ],
              controller: _tabController,
              indicatorColor: Colors.greenAccent,
            ),
          backgroundColor: Colors.black,
        ),
        body: TabBarView(
          controller: _tabController,
          children: <Widget>[
            // 使用GlobalKey关联pendingList
            pendingList(key: pendingListKey),
            completedlist(),
          ],
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: (){
            showDialog(
                context: context,
                builder:(BuildContext context) {
                    return AlertDialog(
                      title: Text("Insert Value",style: TextStyle(color: Colors.white),),
                      content: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          TextField(
                            controller: todoDescription,
                            keyboardType: TextInputType.text,
                            decoration: InputDecoration(
                                border: OutlineInputBorder(),
                                label: Text("Todo Task")
                            ),
                          ),
                          SizedBox(height: 15,),
                          StatefulBuilder(
                            builder: (context,setState){
                              return DropdownButtonFormField(
                                  value: dropdownValue,
                                  isExpanded: true,
                                  decoration: const InputDecoration(
                                    border: OutlineInputBorder(),
                                  ),
                                  elevation: 16,
                                  onChanged: (String? value) {
                                    dropdownValue = value!;
                                    setState(() {});
                                  },
                                  items:[
                                    DropdownMenuItem(child: Text("Top"),value: "Top",),
                                    DropdownMenuItem(child: Text("Intermediate"),value: "Intermediate",),
                                    DropdownMenuItem(child: Text("Low"),value: "Low",),
                                  ]
                              );
                            },
                          )
                        ],
                      ),
                      shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15))),
                      actions: [
                        TextButton(onPressed: (){Navigator.pop(context);}, child: const Text("Cancel",style: TextStyle(color: Colors.white),)),
                        TextButton(onPressed: (){saveData(todoDescription.text.toString());}, child: const Text("OK",style: TextStyle(color: Colors.white),))
                      ],
                    );
                }
            );
          },
          backgroundColor: Colors.greenAccent,
          child: const Icon(Icons.add),
        ),
      );
  }

  saveData(String todoDescription) {
    db.addTask(todoDescription,dropdownValue);
    // 保存完成后直接触发pendingList刷新
    pendingListKey.currentState?.refreshData();
    Navigator.pop(context);
    // 移除不必要的延迟等待,若addTask是异步方法,建议改为await db.addTask(...)后再刷新
  }
}

关键说明

  • 通过GlobalKey可以直接访问子组件的状态类方法,无需繁琐的回调传递
  • 确保数据写入完成后再触发刷新,如果addTask是异步操作,需添加await保证数据已存入SharedPreferences
  • 刷新逻辑直接复用pendingList已有的loadData()方法,重新获取数据并更新UI

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:43:08