简体   繁体   中英

TabBarView doesn't update InhertiedWidget state if tab is changed programatically

I'm using an InhertiedWidget to manage the state of a counter in this app. However, if I update the state and change tabs at the same time, the update doesn't seem to pass through to the individual tabs.

Repro steps

  • Go to tab B
  • Press + button

Expected behaviour

  • The tab changes to A, and the counter updates in the tab

Actual behaviour

  • The tab changes to A, but the counter does not update (even though the actual value changes)

Here's a video to explain what I mean - https://user-images.githubusercontent.com/19492893/186385977-7185afd5-0bec-4291-8085-d2c7f07fc50a.mov

Run on dartpad

import 'package:flutter/material.dart';

void main() => runApp(MainApp());

class MainApp extends StatefulWidget {
  const MainApp({
    Key? key,
  }) : super(key: key);

  @override
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  int count = 1;

  @override
  Widget build(BuildContext context) {
    return CounterInheritedWidget(
      count: count,
      child: MaterialApp(
        home: DefaultTabController(
          length: 2,
          child: CounterTabs(
            increment: increment,
          ),
        ),
      ),
    );
  }

  void increment() {
    setState(() {
      count += 1;
    });
  }
}

class CounterInheritedWidget extends InheritedWidget {
  const CounterInheritedWidget({
    Key? key,
    required this.count,
    required Widget child,
  }) : super(key: key, child: child);

  final int count;

  static CounterInheritedWidget of(BuildContext context) {
    final CounterInheritedWidget? result =
        context.dependOnInheritedWidgetOfExactType<CounterInheritedWidget>();
    assert(result != null, 'No CounterInheritedWidget found in context');
    return result!;
  }

  @override
  bool updateShouldNotify(CounterInheritedWidget old) => count != old.count;
}

class CounterTabs extends StatelessWidget {
  final VoidCallback increment;

  const CounterTabs({Key? key, required this.increment}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    int count = CounterInheritedWidget.of(context).count;
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
            DefaultTabController.of(context)?.animateTo(0);
            increment();
          });
        },
      ),
      appBar: AppBar(
        title: Text("Actual value: $count"),
        bottom: TabBar(
          tabs: [
            Tab(text: "A"),
            Tab(text: "B"),
          ],
        ),
      ),
      body: TabBarView(
        children: [
          Center(child: Text("Tab value: $count")),
          Center(child: Text("Tab value: $count")),
        ],
      ),
    );
  }
}

increment UI update call event is canceled because animationTo , wait for UI update to finish then call animationTo, or set shouldUpdateNotify to always true

Future.delayed(const Duration(milliseconds:100),()=>DefaultTabController.of(context)?.animateTo(0));
         

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM