遇到一个AutomaticKeepAliveClientMixin的问题

4,143 阅读1分钟
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("aaa"),
        ),
        body: Test(),
      ),
    ),
  );
}

class Test extends StatefulWidget {
  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> with SingleTickerProviderStateMixin {
  TabController _controller;
  Key aKey = ValueKey("a");
  Key bKey = ValueKey("b");
  Key cKey = ValueKey("c");

  @override
  void initState() {
    super.initState();
    _controller = TabController(length: 3, vsync: this);
  }

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: <Widget>[
        TabBar(
          labelColor: Colors.blue,
          controller: _controller,
          tabs: <Widget>[
            Tab(
              text: "A",
            ),
            Tab(
              text: "B",
            ),
            Tab(
              text: "C",
            ),
          ],
        ),
        Expanded(
          child: TabBarView(
            controller: _controller,
            children: <Widget>[
              A(),
              B(),
              C(),
            ],
          ),
        ),
      ],
    );
  }
}

class A extends StatefulWidget {
  A({Key key}) : super(key: key);

  @override
  _AState createState() => _AState();
}

class _AState extends State<A> with AutomaticKeepAliveClientMixin {
  int _count = 0;

  void add() {
    setState(() {
      ++_count;
    });
  }

  @override
  void initState() {
    super.initState();
    print("initState A $hashCode count=$_count");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    print("build A $hashCode count=$_count");
    return Scaffold(
      body: Center(
        child: Text("A $_count"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: add,
        child: Icon(Icons.add),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

class B extends StatefulWidget {
  B({Key key}) : super(key: key);
  @override
  _BState createState() => _BState();
}

class _BState extends State<B> with AutomaticKeepAliveClientMixin {
  int _count = 0;

  void add() {
    setState(() {
      ++_count;
    });
  }

  @override
  void initState() {
    super.initState();
    print("initState B $hashCode count=$_count");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    print("build B $hashCode count=$_count");
    return Scaffold(
      body: Center(
        child: Text("B $_count"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: add,
        child: Icon(Icons.add),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

class C extends StatefulWidget {
  C({Key key}) : super(key: key);
  @override
  _CState createState() => _CState();
}

class _CState extends State<C> with AutomaticKeepAliveClientMixin {
  int _count = 0;

  void add() {
    setState(() {
      ++_count;
    });
  }

  @override
  void initState() {
    super.initState();
    print("initState C $hashCode count=$_count");
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    print("build C $hashCode count=$_count");
    return Scaffold(
      body: Center(
        child: Text("C $_count"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: add,
        child: Icon(Icons.add),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}


程序运行后,首先在A页面,然后点击+号将数字变为1,然后点击B标签将数字变为2,然后点击C标签将数字变为3。然后直接点击A页面,这时候会输出initState C,build C和initState B和build B,这时候可以看到AutomaticKeepAliveClientMixin是无效的,这里无效的原因我也不知道,还有个问题就是,经过刚才的操作,现在停留在了A页面,然后点击B标签,切换到B页面,可以看到数字是0,这是正确的,因为B已经重新创建了State,但是如果继续点击C标签,发现虽然刚才C页面的State重新创建了,并且build方法里的_count也是0,但是页面仍然显示3,这里应该是0才对,这个bug我已经提到了官方git issue里:github.com/flutter/flu…