【问题标题】:TabController calling initState again if tabs are clicked in sequence如果按顺序单击选项卡,TabController 会再次调用 initState
【发布时间】:2019-07-08 09:51:07
【问题描述】:

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

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

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

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,并且它已经被第一次调用了。

【问题讨论】:

  • 如果您切换到master 频道,这将按预期工作。修复似乎还没有登陆stable
  • 感谢您的回复。您能否分享该主分支的链接?如果有任何期望什么时候会去stable,如果发布了?
  • 您可以在终端中使用命令flutter channel master 切换到master 频道。不知道什么时候稳定。
  • 感谢您的建议。这行得通。等待一天的稳定版本。

标签: android flutter


【解决方案1】:

此问题已在 master 上得到修复,正如 GitHub issue thread 中所述。

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    • 2017-09-10
    相关资源
    最近更新 更多