flutter - Flutter Widget 中的 didChangeDependencies 钩子(Hook)包含不准确的类数据

标签 flutter dart flutter-layout flutter-dependencies

在下面的代码中,我在 Flutter 中与 LifeCyrles 苦苦挣扎,我可以在 Provider 中更新我的状态,显然,只能在 didChangeDependencies 中更新。 Hook 或在模板小部件中(通过卡在按钮上的事件等)。

好吧,我不介意只有 didChangeDependencies 钩子(Hook)对我有用,但是当我在前面提到的钩子(Hook)中的逻辑依赖于某些类属性时,我在类数据的准确性方面遇到了问题。
我得到数据落后一步(因为它是在 build 我猜是钩子(Hook)之前调用的)。

我无法在构建 Hook 中运行此逻辑,因为它包含更改 Provider 中状态的请求。如果我尝试更改那里的状态,我会遇到以下错误:
setState() or markNeedsBuild() called during build.
或者这个
The setter 'lastPage=' was called on null. Receiver: null Tried calling: lastPage=true
我想做的 : 我有一个包装小部件,它包含三个其他小部件:页脚、页眉和 pageViewer。
当我到达最后一页时,我需要通知我的包装器小部件,以便它做出相应的 react 并隐藏页眉和页脚。

我会很感激这里的任何帮助!

重点代码:

这是问题,必须解决

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:ui_flutter/screens/welcome/welcome_bloc.dart';
import 'package:flutter/scheduler.dart';

class _FooterState extends State<Footer> {

  @override
  void initState() {
    super.initState();
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    final WelcomeBloc _welcome = Provider.of<WelcomeBloc>(context);
    _welcomeBloc = _welcome;
    // this._detectLastPage();
  }

  @override
  Widget build(BuildContext context) {

    return Container(
      alignment: Alignment.bottomCenter,
      padding: EdgeInsets.symmetric(vertical: 30.0, horizontal: 30.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          this.stepper,
          this.nextArrow,
        ],
      ),
    );
  }

  _detectLastPage() {
    // Here I've got inaccurate data

    print(this.widget.currentStep);
}
}


我已经尝试过其他一些钩子(Hook),比如调度程序,但也许我在那里做错了什么。
SchedulerBinding.instance
        .addPostFrameCallback((_) => this._detectLastPage());

它在第一轮集结时只被调用一次,仅此而已。
我这里缺少 Angular 钩子(Hook) AfterViewInit .在这里会很方便。

Mounted在 VueJS 中

如果您想查看整个图片,这就是我的代码的其余部分。
如果您对架构,结构或其他方面有任何建议,欢迎您。由于我是 Flutter 的新手,因此非常感谢。

main.dart
import 'package:flutter/material.dart';
import 'package:ui_flutter/routing.dart';
import 'package:provider/provider.dart';
import 'screens/welcome/welcome_bloc.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => WelcomeBloc()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        initialRoute: '/welcome',
        onGenerateRoute: RouteGenerator.generateRoute,
      ),
    );
  }
}


欢迎.dart (我的包装)
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:provider/provider.dart';
import 'package:ui_flutter/screens/welcome/welcome_bloc.dart';
import './footer.dart';
import './viewWrapper.dart';
import './header.dart';
// import 'package:ui_flutter/routing.dart';

class Welcome extends StatefulWidget {
  @override
  _WelcomeState createState() => _WelcomeState();
}

class _WelcomeState extends State<Welcome> {
  WelcomeBloc _welcomeBloc;

  @override
  Widget build(BuildContext context) {
    final WelcomeBloc _welcome = Provider.of<WelcomeBloc>(context);
    this._welcomeBloc = _welcome;
    print('Welcome: _welcome.currentPage - ${this._welcomeBloc.lastPage}');

    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: <Widget>[
            ViewerWrapper(),
            Footer(
              currentStep: _welcomeBloc.currentPage,
              totalSteps: 3,
              activeColor: Colors.grey[800],
              inactiveColor: Colors.grey[100],
            ),
            WelcomeHeader,
          ],
        ),
      ),
    );
  }
}

WelcomeBloc.dart (我通过提供者的状态)
import 'package:flutter/material.dart';

class WelcomeBloc extends ChangeNotifier {
  PageController _controller = PageController();
  int _currentPage;
  bool _lastPage = false;

  bool get lastPage => _lastPage;

  set lastPage(bool value) {
    _lastPage = value;
    notifyListeners();
  }

  int get currentPage => _currentPage;

  set currentPage(int value) {
    _currentPage = value;
    notifyListeners();
  }

  get controller => _controller;

  nextPage(Duration duration, Curves curve) {
    controller.nextPage(duration: duration, curve: curve);
  }
}

页脚.dart (这就是我在代码最底部遇到数据问题的地方 - _detectLastPage 方法)
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:ui_flutter/screens/welcome/welcome_bloc.dart';
import 'package:flutter/scheduler.dart';

class Footer extends StatefulWidget {
  final int currentStep;
  final int totalSteps;
  final Color activeColor;
  final Color inactiveColor;
  final Duration duration;
  final Function onFinal;
  final Function onStart;

  Footer({
    this.activeColor,
    this.inactiveColor,
    this.currentStep,
    this.totalSteps,
    this.duration,
    this.onFinal,
    this.onStart,
  }) {}

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

class _FooterState extends State<Footer> {
  final double radius = 10.0;
  final double distance = 4.0;
  Container stepper;
  Container nextArrow;
  bool lastPage;
  WelcomeBloc _welcomeBloc;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    final WelcomeBloc _welcome = Provider.of<WelcomeBloc>(context);
    _welcomeBloc = _welcome;
    this._detectLastPage();
  }

  @override
  Widget build(BuildContext context) {
    this._makeStepper();
    this._makeNextArrow();

    return Container(
      alignment: Alignment.bottomCenter,
      padding: EdgeInsets.symmetric(vertical: 30.0, horizontal: 30.0),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          this.stepper,
          this.nextArrow,
        ],
      ),
    );
  }

  _makeCirle(activeColor, inactiveColor, position, currentStep) {
    currentStep = currentStep == null ? 0 : currentStep - 1;
    Color color = (position == currentStep) ? activeColor : inactiveColor;

    return Container(
      height: this.radius,
      width: this.radius,
      margin: EdgeInsets.only(left: this.distance, right: this.distance),
      decoration: BoxDecoration(
          color: color,
          border: Border.all(color: activeColor, width: 2.0),
          borderRadius: BorderRadius.circular(50.0)),
    );
  }

  _makeStepper() {
    List<Container> circles = List();

    for (var i = 0; i < widget.totalSteps; i++) {
      circles.add(
        _makeCirle(this.widget.activeColor, this.widget.inactiveColor, i,
            this.widget.currentStep),
      );
    }

    this.stepper = Container(
      child: Row(
        children: circles,
      ),
    );
  }

  _makeNextArrow() {
    this.nextArrow = Container(
      child: Padding(
        padding: const EdgeInsets.only(right: 8.0),
        child: GestureDetector(
            onTap: () {
              _welcomeBloc.controller.nextPage(
                duration: this.widget.duration ?? Duration(milliseconds: 500),
                curve: Curves.easeInOut,
              );
            },
            child: Icon(
              Icons.arrow_forward,
            )),
      ),
    );
  }

  _onLastPage() {
    if (this.widget.onFinal != null) {
      this.widget.onFinal();
    }
  }

  _onFirstPage() {
    if (this.widget.onStart != null) {
      this.widget.onStart();
    }
  }

  _detectLastPage() {
    // Here I've got inaccurate data 

    int currentPage =
        this.widget.currentStep == null ? 1 : this.widget.currentStep;

    if (currentPage == 1 && this.widget.currentStep == null) {
      this._onFirstPage();
    } else if (currentPage == this.widget.totalSteps) {
      print('lastPage detected');
      setState(() {
        this.lastPage = true;
      });
      _welcomeBloc.lastPage = true;
      this._onLastPage();
    } else {
      setState(() {
        this.lastPage = false;
      });
      _welcomeBloc.lastPage = false;
    }
  }
}

提前致谢!

最佳答案

我也是 Flutter 的新手,但我了解了一些帮助我构建一些应用程序的架构模式。

这是我的做法:

创建 Provider它在运行时为您保存数据。 (在您的情况下,它可以是 Bloc)。坚持一种架构,不要试图将供应商和集团放在同一个项目中。两者都用于状态管理,仅使用一个将是一种很好的做法。

二、Register使用 ChangeNotificationProvider 的提供商或任何其他在数据更改时重建子小部件的类似工作的小部件。

第三,在widget的build方法中获取当变量provider的值改变时应该改变的provider。这样只有相关的小部件被重绘。

对于你的情况,
如果你想在到达最后一页后隐藏页眉和页脚,你可以声明一个变量,比如说 isLastPage设置为 false默认情况下在您的提供商中。
接下来,包装小部件,即 headerfooterChangeNotificationListner
现在,让该小部件根据 isLastPage 的值决定它必须做什么。 ,要么隐藏,要么显示。

我希望这有帮助!

关于flutter - Flutter Widget 中的 didChangeDependencies 钩子(Hook)包含不准确的类数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61598767/

相关文章:

android - TabBar + BottomBarNavigation场景下Controller的长度问题

flutter - 如何从列表中获取特定数据

flutter - 在Flutter中,将整个应用程序包装在WillPopScope中时,不会调用onWillPop

flutter - 在 flutter 中自动在应用程序主屏幕加载上显示警报对话框

Flutter:有没有办法检查小部件是否已构建

Flutter - 针对不同屏幕尺寸的响应式用户界面

flutter - Flutter:如何仅使用其中一个子项覆盖整个专栏

flutter - Dart/Flutter Web 单元测试错误 : Error: Not found: 'dart:html'

java - 如何从 Swift 原生代码到 Flutter 的 'put' 参数

dart - 如何在 AngularDart View 中选择聚合物 Dart 自定义元素