如果依次单击选项卡,则TabController再次调用initState

时间:2019-07-08 09:51:07

标签: android flutter

我是新手。我需要我的应用程序包含4个不同的小部件。每个小部件都有自己的数据,可以通过initState方法从服务器读取。第一次加载布局时,将调用initState并从服务器正常获取数据。因此,除了我注意到如果我单击非相邻选项卡时再次调用了initState之外,其他所有功能都正常工作。

例如:如果我单击选项卡3,然后单击选项卡2,则在第一次加载它们后,以前的状态会很好地加载,并且不会再次调用initState。但是,如果我单击选项卡4,然后单击选项卡1或选项卡2,则在第一次加载它们后,将再次调用两个选项卡的initState并转到服务器以重新获取数据。

我尝试在initState中使用 if(this.mount),但是它被评估为true,并且如果未按相同顺序选择选项卡,仍会再次从服务器获取数据。

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

void main() {
  runApp(MaterialApp(home: HomePage2()));
}

class HomePage2 extends StatefulWidget {
  @override
  _HomePage2State createState() => _HomePage2State();
}

class _HomePage2State extends State<HomePage2> with SingleTickerProviderStateMixin {
  static final List<MyTab> myTabs = [
    MyTab(tab: Tab(icon: Icon(Icons.home)), tabView: SimpleTabView()),
    MyTab(tab: Tab(icon: Icon(Icons.calendar_today)), tabView: SimpleTab2View()),
    MyTab(tab: Tab(icon: Icon(Icons.message)), tabView: SimpleTabView()),
    MyTab(tab: Tab(icon: Icon(Icons.note)), tabView: SimpleTab2View()),
  ];
  var _tabController;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: myTabs.length, vsync: this);
    _tabController.addListener(() {
      //I added a custom tab controller, as I need to be notified with tab change events
    });
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Test Tab Issue'),
        bottom: TabBar(
          tabs: myTabs.map((tab) => tab.tab).toList(),
          controller: _tabController,
        ),
      ),
      body: TabBarView(
        children: myTabs.map((tab) => tab.tabView).toList(),
        controller: _tabController,
      ),
    );
  }
}

class MyTab {
  Tab tab;
  Widget tabView;
  MyTab({this.tab, this.tabView});
}

class SimpleTabView extends StatefulWidget {
  @override
  _SimpleTabViewState createState() => _SimpleTabViewState();
}

class _SimpleTabViewState extends State<SimpleTabView> with AutomaticKeepAliveClientMixin {
  bool isDoingTask = true;

  @override
  void initState() {
    super.initState();
    print('initState called ...');
    if (this.mounted) {
      this.getTask();
    }
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return new Stack(
      children: <Widget>[
        Text('Tab view'),
        Loader(showLoading: isDoingTask),
      ],
    );
  }

  void getTask() async {
    setState(() {
      isDoingTask = true;
    });
    print("${new DateTime.now()} Pause for 3 seconds");
    await new Future.delayed(const Duration(seconds: 3));
    if (!this.mounted) return null;
    setState(() {
      isDoingTask = false;
    });
  }

  @override
  bool get wantKeepAlive => true;
}

//Exactly the same as SimpleTabView except the class name
class SimpleTab2View extends StatefulWidget {....

我希望不会再调用initState方法,因为我已经在使用AutomaticKeepAliveClientMixin,并且它已经是第一次。

1 个答案:

答案 0 :(得分:0)

此问题已在 GitHub issue thread 中提到的 master 上得到解决。