Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/190.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如果按顺序单击选项卡,则TabController将再次调用initState_Android_Flutter - Fatal编程技术网

Android 如果按顺序单击选项卡,则TabController将再次调用initState

Android 如果按顺序单击选项卡,则TabController将再次调用initState,android,flutter,Android,Flutter,我是个新手。我需要我的应用程序包含4个不同的小部件。每个小部件都有自己的数据,可以通过initState方法从服务器读取。第一次加载布局时,将调用initState并从服务器获取数据。所以一切都正常,只是我注意到,如果我单击非相邻选项卡,initState会再次被调用 例如:如果我单击了选项卡3,然后单击了选项卡2,在第一次加载它们之后,上一个状态将被很好地加载,并且不会再次调用initState。但是,如果我单击了选项卡4,然后单击了选项卡1或选项卡2,在第一次加载它们之后,将再次调用这两个选

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

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

我尝试在initState中使用if(this.mounted),但它的计算结果为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 {....
导入“包装:颤振/材料.省道”;
导入“app_layouts.dart”;
void main(){
runApp(MaterialApp(主页:HomePage2());
}
类HomePage2扩展了StatefulWidget{
@凌驾
_HomePage2State createState()=>\u HomePage2State();
}
类_HomePage2State使用SingleTickerProviderStateMixin扩展状态{
静态最终列表myTabs=[
MyTab(选项卡:选项卡(图标:图标(Icons.home)),选项卡视图:SimpleTabView()),
MyTab(tab:tab(icon:icon(Icons.calendar_today)),tabView:SimpleTab2View()),
MyTab(选项卡:选项卡(图标:图标(Icons.message)),选项卡视图:SimpleTabView()),
MyTab(选项卡:选项卡(图标:图标(Icons.note)),选项卡视图:SimpleTab2View(),
];
变量控制器;
@凌驾
void initState(){
super.initState();
_tabController=tabController(长度:myTabs.length,vsync:this);
_tabController.addListener((){
//我添加了一个自定义选项卡控制器,因为我需要得到选项卡更改事件的通知
});
}
@凌驾
无效处置(){
_tabController.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(“测试选项卡问题”),
底部:选项卡栏(
tabs:myTabs.map((tab)=>tab.tab.toList(),
控制器:\ tab控制器,
),
),
正文:选项卡视图(
子项:myTabs.map((tab)=>tab.tabView.toList(),
控制器:\ tab控制器,
),
);
}
}
类MyTab{
选项卡;
控件选项卡视图;
MyTab({this.tab,this.tabView});
}
类SimpleTabView扩展StatefulWidget{
@凌驾
_SimpleTabViewState createState()=>_SimpleTabViewState();
}
类_SimpleTabViewState使用AutomaticEpaLiveClientMixin扩展状态{
bool isDoingTask=true;
@凌驾
void initState(){
super.initState();
打印('initState called…');
如果(本安装){
这个。getTask();
}
}
@凌驾
小部件构建(构建上下文){
super.build(上下文);
返回新堆栈(
儿童:[
文本(“选项卡视图”),
加载程序(显示加载:isDoingTask),
],
);
}
void getTask()异步{
设置状态(){
isDoingTask=true;
});
打印(${new DateTime.now()}暂停3秒);
等待新的未来。延迟(持续时间(秒:3));
如果(!this.mounted)返回null;
设置状态(){
isDoingTask=false;
});
}
@凌驾
bool get wantKeepAlive=>true;
}
//除了类名之外,与SimpleTabView完全相同
类SimpleTab2View扩展了StatefulWidget{。。。。

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

如果您切换到
主频道,这将按预期工作。修复程序似乎还没有落在
稳定的
上。谢谢您的回复。您能分享一个解决方案吗链接到该主分支?如果有任何预期何时会转到
stable
,如果发布?您可以使用终端中的命令
flatter channel master
切换到
master
频道。我不知道它何时会处于稳定状态。谢谢您的建议。这起作用了。等待稳定的重新发布总有一天。