如何使用提供商和Tabbarviews避免使用肮脏的元素,以动态生成颤动的形式?

发布于 2025-01-24 21:10:40 字数 12283 浏览 1 评论 0原文

我对扑朔迷离,在此应用中,我正在制作由从我的服务器中的API获取的JSON构建的多个选项卡清单表单。

为了存储此信息,我将使用一些带有提供商的型号,并在预览屏幕中从服务器中获得响应,并基于用户的输入在此处与无关紧要的输入进行更新。看起来像这样:

**The models**

class KitsEnfermagemList with ChangeNotifier {
  List kits;

  KitsEnfermagemList({required this.kits});

  // a bunch of methods

  void addOrUpdate(KitEnfermagem newKit) {
    if (doesNotExists(newKit)) {
      kits.add(newKit);
      notifyListeners();
    } else {
      KitEnfermagem oldKit = find(newKit)[0];
      oldKit.update(newKit);
    }
  }

  void updateAllFromJson(List<dynamic> json) {
    if (kits.isNotEmpty) {
      for (int i = 0; i < json.length; i++) {
        var newKit = KitEnfermagem.fromJson(json[i]);
        addOrUpdate(newKit);
      }
    } else {
      addMultiple(json.map((kit) => KitEnfermagem.fromJson(kit)).toList());
    }
    return;
  }

class KitEnfermagem with ChangeNotifier {
  String? id;
  String? compartimento;
  int? tipoVeiculo;
  List<ItemPerKit>? itens;

  KitEnfermagem({
    this.id,
    this.compartimento,
    this.tipoVeiculo,
    this.itens,
  });

  void update(KitEnfermagem newKit) {
    compartimento = newKit.compartimento;
    tipoVeiculo = newKit.tipoVeiculo;
    itens = newKit.itens;
    notifyListeners();
  }
}

我如何在主要功能中设置我的changeNotifierProvider:

  Widget build(BuildContext context) {
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);

    return MultiProvider(
      providers: [
        ChangeNotifierProvider<Veiculo>(create: (ctx) => Veiculo()),
        ChangeNotifierProvider<KitEnfermagem>(create: (ctx) => KitEnfermagem()),
        ChangeNotifierProvider<KitsEnfermagemList>(
            create: (ctx) => KitsEnfermagemList(kits: [])),
      ],
      child: MaterialApp(...);

最后我如何修改我的kitsenfermagemlist类,其中包含我用来呈现表单的数据:

  // *I'm instantiating this provider on my build(context) function and passing it as a parameter of _submitForm function, just to be clear.*
  final kitsEnfermagemList = Provider.of<KitsEnfermagemList>(context);

  _submitForm(KitsEnfermagemList kitsEnfermagemList) async {
   // do stuff
      try {
      var responseJson = await _apiService.get(_endpoint);
      setState(() {
        _isLoading = false;
      });
     **kitsEnfermagemList.updateAllFromJson(responseJson);
      Navigator.of(context)
          .pushReplacementNamed(Routes.checklistEnfermagemForm);**
    } on... // handling errors
  }

我在动态定义的数量时遇到了一些麻烦我需要为表单渲染的标签,因此我尝试将提供商用作州经理并在我的TabController之前实例化,因此我超越了DIDCHANGEDEPENTISENCIES方法。

class _ChecklistEnfermagemFormViewState
    extends State<ChecklistEnfermagemFormView>
    with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {

  @override
  bool get wantKeepAlive => true;

  int currentTab = 0;
  final Map<String, dynamic> _formData = {'checklists_kit': []};
  late TabController _tabController;
  late Veiculo veiculo;
  late KitsEnfermagemList kitsEnfermagemList;
  late int tabsLength;

    @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    veiculo = Provider.of<Veiculo>(context);
    kitsEnfermagemList = Provider.of<KitsEnfermagemList>(context);
    assert(kitsEnfermagemList.isNotEmpty == true);
    tabsLength = kitsEnfermagemList.length + viewModel.othersTabsLength;
    kitsEnfermagemList.kits
        .map((kit) => _formData['checklists_kit'].add(ChecklistKit().toJson()));
    _tabController = TabController(length: tabsLength, vsync: this);
  }

    TabBarView _buildTabBarView() {
      return TabBarView(
        physics: const NeverScrollableScrollPhysics(),
        controller: _tabController,
        children: <Widget>[
          // dynamically generating each tab
        ],
      ),
    );

    return CustomWillPopScope(
      child: Scaffold(
        appBar: appBar,
        body: AppBackground(
          child: _isLoading
              ? const Center(child: CircularProgressIndicator())
              : _buildTabBarView(),
        ),
      ),
    );
  }
}

我遇到的问题是在我渲染以前的小部件的第一刻:

======== Exception caught by widgets library =======================================================
The following assertion was thrown while rebuilding dirty elements:
_ChecklistEnfermagemFormViewState is a SingleTickerProviderStateMixin but multiple tickers were created.

A SingleTickerProviderStateMixin can only be used as a TickerProvider once.

If a State is used for multiple AnimationController objects, or if it is passed to other objects and those objects might use it more than one time in total, then instead of mixing in a SingleTickerProviderStateMixin, use a regular TickerProviderStateMixin.

The relevant error-causing widget was: 
  ChecklistEnfermagemFormView ChecklistEnfermagemFormView:file:///mnt/5dfbbeb6-7a4a-4a3a-9f0d-dd39eb411d55/Projetos/_mobile/dirigir_assessoria/lib/main.dart:110:21
When the exception was thrown, this was the stack: 
#0      SingleTickerProviderStateMixin.createTicker.<anonymous closure> (package:flutter/src/widgets/ticker_provider.dart:188:7)
#1      SingleTickerProviderStateMixin.createTicker (package:flutter/src/widgets/ticker_provider.dart:197:6)
#2      new AnimationController.unbounded (package:flutter/src/animation/animation_controller.dart:279:21)
#3      new TabController (package:flutter/src/material/tab_controller.dart:110:50)
#4      _ChecklistEnfermagemFormViewState.didChangeDependencies (package:dirigir_assessoria/screens/enfermagem/checklist_enfermagem_form_screen.dart:159:22)
#5      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4925:13)
#6      Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#7      BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#8      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21)
#9      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:363:5)
#10     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
#11     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1081:9)
#12     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:995:5)
#16     _invoke (dart:ui/hooks.dart:151:10)
#17     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#18     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
The element being rebuilt at the time was index 3 of 7: ChecklistEnfermagemFormView
  dirty
  dependencies: [_InheritedTheme, MediaQuery, _InheritedProviderScope<KitsEnfermagemList>, _LocalizationsScope-[GlobalKey#a34b4], _InheritedProviderScope<Veiculo>]
  state: _ChecklistEnfermagemFormViewState#53df3(ticker inactive)
====================================================================================================

======== Exception caught by scheduler library =====================================================
buildScope missed some dirty elements.
The list of dirty elements at the end of the buildScope call was: 
  : HomeScreen
    dependencies: [_InheritedTheme, MediaQuery, _LocalizationsScope-[GlobalKey#a34b4]]
  : ChecklistEnfermagemFormView
    dirty
    dependencies: [_InheritedTheme, MediaQuery, _InheritedProviderScope<KitsEnfermagemList>, _LocalizationsScope-[GlobalKey#a34b4], _InheritedProviderScope<Veiculo>]
    state: _ChecklistEnfermagemFormViewState#53df3(ticker inactive)
  : Scaffold
    dependencies: [Directionality, _InheritedTheme, MediaQuery, _ScaffoldMessengerScope, UnmanagedRestorationScope, _LocalizationsScope-[GlobalKey#a34b4]]
    state: ScaffoldState#aa553(tickers: tracking 2 tickers)
  : Scaffold
    dependencies: [Directionality, _InheritedTheme, MediaQuery, UnmanagedRestorationScope, _ScaffoldMessengerScope, _LocalizationsScope-[GlobalKey#a34b4]]
    state: ScaffoldState#07a62(tickers: tracking 2 tickers)
  : AppBar
    dependencies: [_InheritedTheme, _ScrollNotificationObserverScope, MediaQuery, FlexibleSpaceBarSettings, _ModalScopeStatus, _LocalizationsScope-[GlobalKey#a34b4]]
    state: _AppBarState#06d17
  : Text
    "Checklist da Enfermagem"
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Gaveta 1"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala Laringoscópio"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Balcão/Salão"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Maleta Psicotrópicos"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Baú"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Assinatura"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Armário A"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Gaveta 2"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Régua"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala de Vias Aéreas e Oxigenoterapia"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala de Trauma"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Bolsa de Sinais Vitais"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala de Procedimento"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala de Medicação e Acesso Venoso"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Gaveta 3"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Armário B"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Fotos"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [DefaultTextStyle, MediaQuery]
  : Text
    "Inicial"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [DefaultTextStyle, MediaQuery]
  ...
====================================================================================================

我已经尝试使用tickerproviderstatemixin代替singletickerproviderstatemixin,它停止显示错误,但也引入了一些意外的行为,例如导致回到返回错误最初的标签如果我跳到下一个键盘后,我将其剩余的键盘删除,所以我得出的结论是,它没有解决问题,它只是隐藏了它...

我在无需动态的情况下就不太动态地构建了另一种形式国家管理人员效果很好。但老实说,这是我第一次尝试使用提供商,我觉得我缺少某些实施规则。谁能帮忙?

I'm relatively new to Flutter and in this app I'm making a multiple tab checklist form built from a JSON fetched from an API in my server.

To store this info I'm using a few models with Provider and updating them as soon as I get the response from the server in a preview screen, based on an input from the user that's not relevant here. It looks like this:

**The models**

class KitsEnfermagemList with ChangeNotifier {
  List kits;

  KitsEnfermagemList({required this.kits});

  // a bunch of methods

  void addOrUpdate(KitEnfermagem newKit) {
    if (doesNotExists(newKit)) {
      kits.add(newKit);
      notifyListeners();
    } else {
      KitEnfermagem oldKit = find(newKit)[0];
      oldKit.update(newKit);
    }
  }

  void updateAllFromJson(List<dynamic> json) {
    if (kits.isNotEmpty) {
      for (int i = 0; i < json.length; i++) {
        var newKit = KitEnfermagem.fromJson(json[i]);
        addOrUpdate(newKit);
      }
    } else {
      addMultiple(json.map((kit) => KitEnfermagem.fromJson(kit)).toList());
    }
    return;
  }

class KitEnfermagem with ChangeNotifier {
  String? id;
  String? compartimento;
  int? tipoVeiculo;
  List<ItemPerKit>? itens;

  KitEnfermagem({
    this.id,
    this.compartimento,
    this.tipoVeiculo,
    this.itens,
  });

  void update(KitEnfermagem newKit) {
    compartimento = newKit.compartimento;
    tipoVeiculo = newKit.tipoVeiculo;
    itens = newKit.itens;
    notifyListeners();
  }
}

How I setup my ChangeNotifierProvider in my main function:

  Widget build(BuildContext context) {
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);

    return MultiProvider(
      providers: [
        ChangeNotifierProvider<Veiculo>(create: (ctx) => Veiculo()),
        ChangeNotifierProvider<KitEnfermagem>(create: (ctx) => KitEnfermagem()),
        ChangeNotifierProvider<KitsEnfermagemList>(
            create: (ctx) => KitsEnfermagemList(kits: [])),
      ],
      child: MaterialApp(...);

And finally how I'm modifying my KitsEnfermagemList class, which contains the data that I'm using to render the form:

  // *I'm instantiating this provider on my build(context) function and passing it as a parameter of _submitForm function, just to be clear.*
  final kitsEnfermagemList = Provider.of<KitsEnfermagemList>(context);

  _submitForm(KitsEnfermagemList kitsEnfermagemList) async {
   // do stuff
      try {
      var responseJson = await _apiService.get(_endpoint);
      setState(() {
        _isLoading = false;
      });
     **kitsEnfermagemList.updateAllFromJson(responseJson);
      Navigator.of(context)
          .pushReplacementNamed(Routes.checklistEnfermagemForm);**
    } on... // handling errors
  }

I was having some trouble defining dynamically the amount of tabs I would need to render for the form, so I tried to use Provider as a state manager and instantiate before my TabController, and to do so I overrode didChangeDependencies method.

class _ChecklistEnfermagemFormViewState
    extends State<ChecklistEnfermagemFormView>
    with SingleTickerProviderStateMixin, AutomaticKeepAliveClientMixin {

  @override
  bool get wantKeepAlive => true;

  int currentTab = 0;
  final Map<String, dynamic> _formData = {'checklists_kit': []};
  late TabController _tabController;
  late Veiculo veiculo;
  late KitsEnfermagemList kitsEnfermagemList;
  late int tabsLength;

    @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    veiculo = Provider.of<Veiculo>(context);
    kitsEnfermagemList = Provider.of<KitsEnfermagemList>(context);
    assert(kitsEnfermagemList.isNotEmpty == true);
    tabsLength = kitsEnfermagemList.length + viewModel.othersTabsLength;
    kitsEnfermagemList.kits
        .map((kit) => _formData['checklists_kit'].add(ChecklistKit().toJson()));
    _tabController = TabController(length: tabsLength, vsync: this);
  }

    TabBarView _buildTabBarView() {
      return TabBarView(
        physics: const NeverScrollableScrollPhysics(),
        controller: _tabController,
        children: <Widget>[
          // dynamically generating each tab
        ],
      ),
    );

    return CustomWillPopScope(
      child: Scaffold(
        appBar: appBar,
        body: AppBackground(
          child: _isLoading
              ? const Center(child: CircularProgressIndicator())
              : _buildTabBarView(),
        ),
      ),
    );
  }
}

And the problem I'm getting is this right on the first moment I render the previous widget:

======== Exception caught by widgets library =======================================================
The following assertion was thrown while rebuilding dirty elements:
_ChecklistEnfermagemFormViewState is a SingleTickerProviderStateMixin but multiple tickers were created.

A SingleTickerProviderStateMixin can only be used as a TickerProvider once.

If a State is used for multiple AnimationController objects, or if it is passed to other objects and those objects might use it more than one time in total, then instead of mixing in a SingleTickerProviderStateMixin, use a regular TickerProviderStateMixin.

The relevant error-causing widget was: 
  ChecklistEnfermagemFormView ChecklistEnfermagemFormView:file:///mnt/5dfbbeb6-7a4a-4a3a-9f0d-dd39eb411d55/Projetos/_mobile/dirigir_assessoria/lib/main.dart:110:21
When the exception was thrown, this was the stack: 
#0      SingleTickerProviderStateMixin.createTicker.<anonymous closure> (package:flutter/src/widgets/ticker_provider.dart:188:7)
#1      SingleTickerProviderStateMixin.createTicker (package:flutter/src/widgets/ticker_provider.dart:197:6)
#2      new AnimationController.unbounded (package:flutter/src/animation/animation_controller.dart:279:21)
#3      new TabController (package:flutter/src/material/tab_controller.dart:110:50)
#4      _ChecklistEnfermagemFormViewState.didChangeDependencies (package:dirigir_assessoria/screens/enfermagem/checklist_enfermagem_form_screen.dart:159:22)
#5      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4925:13)
#6      Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#7      BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#8      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:882:21)
#9      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:363:5)
#10     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
#11     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1081:9)
#12     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:995:5)
#16     _invoke (dart:ui/hooks.dart:151:10)
#17     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#18     _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
The element being rebuilt at the time was index 3 of 7: ChecklistEnfermagemFormView
  dirty
  dependencies: [_InheritedTheme, MediaQuery, _InheritedProviderScope<KitsEnfermagemList>, _LocalizationsScope-[GlobalKey#a34b4], _InheritedProviderScope<Veiculo>]
  state: _ChecklistEnfermagemFormViewState#53df3(ticker inactive)
====================================================================================================

======== Exception caught by scheduler library =====================================================
buildScope missed some dirty elements.
The list of dirty elements at the end of the buildScope call was: 
  : HomeScreen
    dependencies: [_InheritedTheme, MediaQuery, _LocalizationsScope-[GlobalKey#a34b4]]
  : ChecklistEnfermagemFormView
    dirty
    dependencies: [_InheritedTheme, MediaQuery, _InheritedProviderScope<KitsEnfermagemList>, _LocalizationsScope-[GlobalKey#a34b4], _InheritedProviderScope<Veiculo>]
    state: _ChecklistEnfermagemFormViewState#53df3(ticker inactive)
  : Scaffold
    dependencies: [Directionality, _InheritedTheme, MediaQuery, _ScaffoldMessengerScope, UnmanagedRestorationScope, _LocalizationsScope-[GlobalKey#a34b4]]
    state: ScaffoldState#aa553(tickers: tracking 2 tickers)
  : Scaffold
    dependencies: [Directionality, _InheritedTheme, MediaQuery, UnmanagedRestorationScope, _ScaffoldMessengerScope, _LocalizationsScope-[GlobalKey#a34b4]]
    state: ScaffoldState#07a62(tickers: tracking 2 tickers)
  : AppBar
    dependencies: [_InheritedTheme, _ScrollNotificationObserverScope, MediaQuery, FlexibleSpaceBarSettings, _ModalScopeStatus, _LocalizationsScope-[GlobalKey#a34b4]]
    state: _AppBarState#06d17
  : Text
    "Checklist da Enfermagem"
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Gaveta 1"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala Laringoscópio"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Balcão/Salão"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Maleta Psicotrópicos"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Baú"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Assinatura"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Armário A"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Gaveta 2"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Régua"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala de Vias Aéreas e Oxigenoterapia"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala de Trauma"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Bolsa de Sinais Vitais"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala de Procedimento"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Mala de Medicação e Acesso Venoso"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Gaveta 3"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Armário B"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [MediaQuery, DefaultTextStyle]
  : Text
    "Fotos"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [DefaultTextStyle, MediaQuery]
  : Text
    "Inicial"
    debugLabel: englishLike labelLarge 2014
    inherit: false
    size: 14.0
    weight: 500
    baseline: alphabetic
    dependencies: [DefaultTextStyle, MediaQuery]
  ...
====================================================================================================

I've already tried to use TickerProviderStateMixin instead of SingleTickerProviderStateMixin and it stops showing the error, but also introduces some unexpected behaviors, such as leading back to the initial tab if I dismiss its remaining keyboard after I've jumped to the next one, so I concluded that it was not solving the problem, it was just hiding it...

I've built another form less dynamically without the need of an state management and it's working fine. But honestly this is first time I'm trying to use Provider and I feel like I'm missing some implementation rule. Can anyone help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

走野 2025-01-31 21:10:40

SingletickerProviderstateMixintickerproviderstatemixin替换,

这是因为重建Tabs Controller更改TABS计数会导致多个控制器立即存在。每个控制器都取决于带有vsync值的股票。因此,应该有多个股票来支持这一点。


另一个注意事项:

使用DidchangeDepentencies这样的生命周期方法会导致对提供商的不必要呼叫。 状态的依赖性更改。如果您正在使用它,因为我猜想避免使用上下文,并希望其中的代码仅执行一次,我建议您这样使用:

bool _isInit = true;

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  if(_isInit) {
    // The following code is executed only once
    veiculo = Provider.of<Veiculo>(context);
    kitsEnfermagemList = Provider.of<KitsEnfermagemList>(context);
    assert(kitsEnfermagemList.isNotEmpty == true);
    tabsLength = kitsEnfermagemList.length + viewModel.othersTabsLength;
    kitsEnfermagemList.kits
        .map((kit) => _formData['checklists_kit'].add(ChecklistKit().toJson()));
    _tabController = TabController(length: tabsLength, vsync: this);
  }
  _isInit = false;
}

如果您真的想在每个依赖关系更改上执行代码,则可以使用“ noreforler”> didupdatewidget生命周期方法。

Replace your SingleTickerProviderStateMixin with TickerProviderStateMixin

This is because rebuilding the tabs controller to change the tabs count causes multiple controllers to be present at once. And each controller depends on a Ticker with the vsync value. So there should be multiple Tickers to support that.


Another note:

Using the didChangeDependencies lifecycle method like this causes unnecessary calls to your provider. Because this method is called right after initState AND when a dependency of the state changes. If you're using it as I'm guessing to avoid using context and want the code inside it to execute only once, I recommend you use it like this:

bool _isInit = true;

@override
void didChangeDependencies() {
  super.didChangeDependencies();
  if(_isInit) {
    // The following code is executed only once
    veiculo = Provider.of<Veiculo>(context);
    kitsEnfermagemList = Provider.of<KitsEnfermagemList>(context);
    assert(kitsEnfermagemList.isNotEmpty == true);
    tabsLength = kitsEnfermagemList.length + viewModel.othersTabsLength;
    kitsEnfermagemList.kits
        .map((kit) => _formData['checklists_kit'].add(ChecklistKit().toJson()));
    _tabController = TabController(length: tabsLength, vsync: this);
  }
  _isInit = false;
}

If you really want to execute code on every dependency change, then you can use the didUpdateWidget lifecycle method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文