如何使选项卡和选项卡栏视图在 flutter 中动态显示,以便它能够响应 api?

How do I make a tab and tab bar view dynamic in flutter so that it will ha on the response from an api?

我正在尝试创建一个列表,将数据添加到列表基于 已收到回复,但无法正常工作。

我尝试在添加之前循环遍历数据库以检查数据是否存在 到列表中。我好像做的不是很好

我的挑战是动态控制我添加到列表中的内容。这样它就会根据那个改变。

    Updated the codes.
      //Defualt tab controller
       DefaultTabController(
        length: tabs.length,
       child: Column(
          children: [
            Container(
              child: TabBar(
                labelColor: HexColor("#006E40"),
                unselectedLabelColor: Colors.black,
                indicatorColor: HexColor("#006E40"),
                indicatorWeight: 3,
                indicatorPadding: (EdgeInsets.symmetric(horizontal: 
                10.0)),
                isScrollable: true,
              //  controller: _tabController,
                tabs: tabs ), // tabs List 
            ),
            SizedBox(height: 15),
            Container(
              margin: const EdgeInsets.only(bottom: 20.0),
              height: MediaQuery
                  .of(context)
                  .size
                  .height * 0.8,
              child: Padding(
                padding: const EdgeInsets.only(bottom: 28.0),
                child: TabBarView(
                  children: tabsItems ), // Tab Bar List
              ),}
 // Checking whether the item already exist then adding to the list 
 //  based on result
  Lsit<DatabaseItemsPastaSelf> databaseItemsPasta = [] 

  Future readPastaItems() async {
this.databaseItemsPasta = await 
  PastaDatabaseSelf.instance.readAllItems();
   for(int i = 0; i<databaseItemsPasta.length; i++){
    if (databaseItemsPasta.length != 0) {
     tabs.add(
      Padding(
        padding: const EdgeInsets.only(top: 20),
        child: Text(
          "Fruits",
          style: TextStyle(fontWeight: FontWeight.w700, fontSize: 
               14),
            ),
          ),
        );
        tabsItems.add(PastaAndNoodlesSelf());
        break;
        }
      }
      return databaseItemsPasta.length;
      }

    List<DatabaseItemsSugarSelf> databaseItemsSugar = [];

    Future readSugarItems() async {
    this.databaseItemsSugar = await 
    SugarDatabaseSelf.instance.readAllItems();
     for(int i = 0; i<databaseItemsSugar.length; i++){
       if (databaseItemsSugar.length != 0) {
       tabs.add(
         Padding(
          padding: const EdgeInsets.only(top: 20),
           child: Text(
           "Foods",
            style: TextStyle(fontWeight: FontWeight.w700, fontSize: 
          14),
        ),
      ),
    );
     tabsItems.add(SugarSelf());
       break;
  }
   }
   return databaseItemsSugar.length;
    }


   List<Widget> tabs = [];
  List<Widget> tabsItems = [];
  }

      

您可以如下使用FutureBuilder、map函数和状态管理

FutureBuilder:侦听获取数据状态。 map 函数:迭代抛出数据列表。 更新数据列表状态的状态管理。

请更新

readPastaItems()

成为

var tabIndex = 0;
bool isLoadingData = false;

List<dynamic> databaseItemsPasta = [];


Future readPastaItems() async {
  isLoadingData = true;
  await PastaDatabaseSelf.instance.readAllItems().then((records) {
    this.databaseItemsPasta = records;
    isLoadingData = false;
  });
}

并更新

DefaultTabController

用 FutureBuilder 包装

FutureBuilder(
future: Future.delayed(Duration.zero, () => readPastaItems()),
builder: (context, snapshot) {

  if(isLoadingData) return CircularProgressIndicator();
  if(snapshot.hasError) return Text('error');
  if(!snapshot.hasData || this.databaseItemsPasta.isEmpty) return Text('no data');

  if(this.databaseItemsPasta.length > 0)  return DefaultTabController(
    length: databaseItemsPasta?.length ?? 0,
    initialIndex: tabIndex,
    child: Scaffold(
      appBar: AppBar(),
      body: TabBarView(
        physics: NeverScrollableScrollPhysics(),
        children: databaseItemsPasta.map((databaseItem) =>
            Padding(padding: const EdgeInsets.only(top: 12, bottom: 12), child: Text('${databaseItem.toString()}')),
        ).toList(),
      ),
      bottomNavigationBar: TabBar(
        labelColor: Colors.black45,
        tabs: databaseItemsPasta.map((databaseItem) =>
            Padding(padding: const EdgeInsets.only(top: 12, bottom: 12), child: Text('${databaseItem.toString()}')),
        ).toList(),
      ),
    ),
  );

  return SizedBox();
}
)