Авария Flutter Animtion со следующим утверждением было выдано при уведомлении слушателей об ошибке AnimationController - PullRequest
0 голосов
/ 10 декабря 2018

Я пытаюсь создать страницу входа в Flutter и хочу анимировать перед тем, как перейти на следующую страницу.Все работает нормально, кроме как при выполнении (Плохая информация в логине, поэтому она вызывает функцию «failedLoginAnimation» и после ввода правильной информации в форму), в конце она начинает анимироваться, мое приложение вылетает и показывает мне, но когда я вхожуПравильно, если вы сделаете ошибку, прежде чем все заработает.PS: я новичок, чтобы трепетать около месяца и даже больше для анимации.

    ══╡ EXCEPTION CAUGHT BY ANIMATION LIBRARY ╞═════════════════════════════════════════════════════════
I/flutter (11398): The following assertion was thrown while notifying listeners for AnimationController:
I/flutter (11398): Looking up a deactivated widget's ancestor is unsafe.
I/flutter (11398): At this point the state of the widget's element tree is no longer stable. To safely refer to a
I/flutter (11398): widget's ancestor in its dispose() method, save a reference to the ancestor by calling
I/flutter (11398): inheritFromWidgetOfExactType() in the widget's didChangeDependencies() method.
I/flutter (11398): 
I/flutter (11398): When the exception was thrown, this was the stack:
I/flutter (11398): #0      Element._debugCheckStateIsActiveForAncestorLookup.<anonymous closure> (package:flutter/src/widgets/framework.dart:3232:9)
I/flutter (11398): #1      Element._debugCheckStateIsActiveForAncestorLookup (package:flutter/src/widgets/framework.dart:3241:6)
I/flutter (11398): #2      Element.ancestorStateOfType (package:flutter/src/widgets/framework.dart:3289:12)
I/flutter (11398): #3      Navigator.of (package:flutter/src/widgets/navigator.dart:1271:19)
I/flutter (11398): #4      Navigator.popAndPushNamed (package:flutter/src/widgets/navigator.dart:825:22)
I/flutter (11398): #5      StaggerAnimationSignIn.build.<anonymous closure> (package:test/premium/pages/login/loginAnimation.dart:146:25)
I/flutter (11398): #6      _AnimationController&Animation&AnimationEagerListenerMixin&AnimationLocalListenersMixin.notifyListeners (package:flutter/src/animation/listener_helpers.dart:124:19)
I/flutter (11398): #7      AnimationController._tick (package:flutter/src/animation/animation_controller.dart:693:5)
I/flutter (11398): #8      Ticker._tick (package:flutter/src/scheduler/ticker.dart:228:5)
I/flutter (11398): #9      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter (11398): #10     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleBeginFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:906:11)
I/flutter (11398): #11     __InternalLinkedHashMap&_HashVMBase&MapMixin&_LinkedHashMapMixin.forEach (dart:collection/runtime/libcompact_hash.dart:370:8)
I/flutter (11398): #12     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleBeginFrame (package:flutter/src/scheduler/binding.dart:904:17)
I/flutter (11398): #13     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleBeginFrame (package:flutter/src/scheduler/binding.dart:834:5)
I/flutter (11398): #14     _invoke1 (dart:ui/hooks.dart:159:13)
I/flutter (11398): #15     _beginFrame (dart:ui/hooks.dart:129:3)
I/flutter (11398): 
I/flutter (11398): The AnimationController notifying listeners was:
I/flutter (11398):   AnimationController#97d39(⏭ 1.000; paused)
I/flutter (11398): ════════════════════════════════════════════════════════════════════════════════════════════════════

Мой LoginPage

import 'package:flutter/material.dart';
import 'loginAnimation.dart';
import 'freeAccessAnimation.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/animation.dart';
import 'package:test/premium/tools/jsonTools.dart';
import 'dart:async';
import 'package:test/premium/tools/design/color/designColors.dart';
import './Components/PremiumLink.dart';
import './Components/ForgotPasswordLink.dart';
import './Components/Logo.dart';
import './Components/SignInButton.dart';
import './Components/FreeAccessButton.dart';
import 'package:flutter/services.dart';
import 'package:flutter/scheduler.dart' show timeDilation;
import 'package:test/premium/tools/internet/checkInternet.dart';
import 'package:test/premium/pages/tools/alerts.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:test/premium/variables/variablesApp.dart';
import 'package:test/premium/tools/internet/sendHTTPRequest.dart';


class LoginScreen extends StatefulWidget {
  const LoginScreen({Key key}) : super(key: key);
  @override
  LoginScreenState createState() => new LoginScreenState();
}


class LoginScreenState extends State<LoginScreen>
    with TickerProviderStateMixin {
  static bool hasFinishedLogin;
  static bool hasFailedLogin;

  static String userLoginToken ;
  static String tokenFileExist ;
  static String backToLogin;
  static bool isFirstCallAction;
  static bool hasFinishLogAnim;

  AnimationController _loginButtonController;
  AnimationController _freeButtonController;

  static final usernameController = TextEditingController();
  static final passwordController = TextEditingController();

  static var animationStatusLogin = 0;
  static var animationStatusFree = 0;

  Future pause(Duration d) => new Future.delayed(d);

  _launchURL(String url) async {
    if (await canLaunch(url)) {
      await launch(url);
    } else {
      throw 'Could not launch $url';
    }
  }

  void tokensManagement(){
    if(userLoginToken == null && tokenFileExist == null && backToLogin == "true") {
      JTools.deleteFileToken().then((e){
        if(e == "Token has been deleted"){
          setState(() {
            tokenFileExist = 'false';
            userLoginToken = null;
            backToLogin = 'false';
          });

        }
      });

    }else{
      JTools.readDataToken().then((e){
        String _token = e;
        pause(new Duration(milliseconds: 500)).then((e){
          JTools.tokenFileExist().then((value){
            tokenFileExist = value.toString();
            userLoginToken = _token;
          }).then((b){
            if(_token != null){
              if(userLoginToken.isNotEmpty && tokenFileExist == 'true'){
                //TODO: on loading
                APIToken.token = _token;
                CheckInternet().checkInternet().then((e){
                  if(e == true){
                        PostHTTP().sendRequestAPI(APIToken.token, 'membership').then((value){
                          if(value['status'] == "200"){
                            String membership = value['membership'];
                            print(membership);
                            if(membership == "138" || membership == "136"){
                              print('User is premium');
                              Navigator.of(context).pushNamed('/main');
                            }else {
                              print("User isn't premium ");
                              JTools.deleteFileToken().then((e) {
                                if (e == "Token has been deleted") {
                                  setState(() {
                                    tokenFileExist = 'false';
                                    userLoginToken = null;
                                  });
                                  pause(Duration(milliseconds: 1000)).then((e){
                                    Alerts(context: context).alertNotPremium();
                                  });
                                }
                              });
                            }
                          }else{
                            if(value['status'] == "404"){
                                setState(() {
                                  tokenFileExist = 'false';
                                  userLoginToken = null;
                                  backToLogin = 'false';
                                });
                                pause(Duration(milliseconds: 1000)).then((e){
                                  Alerts(context: context).alertErrorConnectionServer();
                                });

                            }
                            if(value['status'] == "401" || value['status'] == "403")
                            {print("User isn't premium ");
                            JTools.deleteFileToken().then((e) {
                              if (e == "Token has been deleted") {
                                setState(() {
                                  tokenFileExist = 'false';
                                  userLoginToken = null;
                                  backToLogin = 'false';
                                });
                                pause(Duration(milliseconds: 1000)).then((e){
                                  Alerts(context: context).alertNotPremium();
                                });
                              }
                            });}
                          }
                        });
                  }else{
                    Alerts(context: context).alertInternet();
                    failedLoginAnimation();
                  }
                });
              }
              else{
                setState(() {

                });
              }
            }else{
              setState(() {

              });
            }
          });
        });
      });
    }
  }

  @override
  void initState() {
    super.initState();
    _loginButtonController = new AnimationController(
        duration: new Duration(milliseconds: 3000), vsync: this);
    _freeButtonController = new AnimationController(
        duration: new Duration(milliseconds: 3000), vsync: this);
    tokensManagement();
    animationStatusLogin = 0;
    animationStatusFree = 0;
    print('init LOGIN');
  }

  @override
  void dispose() {
    super.dispose();
    _loginButtonController.dispose();
    _freeButtonController.dispose();
  }

  Future<Null> _playAnimationLogin() async {
    try {
      await _loginButtonController.forward();
    } on TickerCanceled {}
  }

  Future<Null> _playAnimationFree() async {
    try {
      await _freeButtonController.forward();
      await _freeButtonController.reverse();
    } on TickerCanceled {}
  }

  Widget formLogin(){
    return new Container(
      margin: new EdgeInsets.symmetric(horizontal: 20.0),
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: <Widget>[
          new Form(
              child: new Column(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  new Container(
                    decoration: new BoxDecoration(
                      border: new Border(
                        bottom: new BorderSide(
                          width: 0.5,
                          color: DesignColors.animatedLoginColor,
                        ),
                      ),
                    ),
                    child: new TextFormField(
                      controller: usernameController,
                      keyboardType: TextInputType.emailAddress,
                      style: const TextStyle(
                        color: Colors.white,
                      ),
                      decoration: new InputDecoration(
                        icon: new Icon(
                          Icons.person_outline,
                          color: Colors.white,
                        ),
                        border: InputBorder.none,
                        hintText: "Email/Username",
                        hintStyle: const TextStyle(color: Colors.white, fontSize: 15.0),
                        contentPadding: const EdgeInsets.only(
                            top: 30.0, right: 30.0, bottom: 30.0, left: 5.0),
                      ),
                    ),
                  ),
                  new Container(
                    decoration: new BoxDecoration(
                      border: new Border(
                        bottom: new BorderSide(
                          width: 0.5,
                          color: DesignColors.animatedLoginColor,
                        ),
                      ),
                    ),
                    child: new TextFormField(
                      controller: passwordController,
                      obscureText: true,
                      style: const TextStyle(
                        color: Colors.white,
                      ),
                      decoration: new InputDecoration(
                        icon: new Icon(
                          Icons.lock_outline,
                          color: Colors.white,
                        ),
                        border: InputBorder.none,
                        hintText: "Password",
                        hintStyle: const TextStyle(color: Colors.white, fontSize: 15.0),
                        contentPadding: const EdgeInsets.only(
                            top: 30.0, right: 30.0, bottom: 30.0, left: 5.0),
                      ),
                    ),
                  ),
                ],
              )),
        ],
      ));
  }

  void failedLoginAnimation(){
    setState(() {
      hasFailedLogin = true;
      _playAnimationLogin();
      animationStatusLogin = 0;
    });
  }

  Widget logPage(){
    return new WillPopScope(
        onWillPop: () async => false,
        child: new Scaffold(
            backgroundColor: DesignColors.backgroundColor,
            body: Center(
              child: Theme(
                data: ThemeData(splashColor: Colors.transparent, textSelectionHandleColor: Colors.blue, highlightColor: Colors.transparent),
                child:new ListView(
                  shrinkWrap: true,
                  children: <Widget>[
                    new Stack(
                      alignment: AlignmentDirectional.bottomCenter,
                      children: <Widget>[
                        new Column(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          children: <Widget>[
                            new Logo(image: DecorationImage(image: ExactAssetImage('assets/images/AppLogo.png'), fit: BoxFit.cover),),
                            formLogin(),
                            new PremiumLink(action: (){_launchURL("someurl");}),
                            new ForgotPasswordLink(action: (){_launchURL("someurl");}),
                          ],
                        ),
                        animationStatusLogin == 0
                            ? new Padding(
                          padding: const EdgeInsets.only(bottom: 160.0),
                          child: new InkWell(
                              onTap: () {
                                setState(() {
                                  animationStatusLogin = 1;
                                  hasFinishedLogin = false;
                                  hasFinishLogAnim = false;
                                  hasFailedLogin = false;
                                  isFirstCallAction = true;
                                });
                                _playAnimationLogin();
                              },
                              child: new SignIn()),
                        )
                            : new StaggerAnimationSignIn( action: (){
                          CheckInternet().checkInternet().then((e){
                            if(e == true){
                              PostHTTP().sendLogin({'username': usernameController.text, 'password': passwordController.text}).then((e){
                                String responseStatus = e['status'];
                                if(responseStatus != "200"){
                                  Alerts(context: context).alertFalseInfosLogin();
                                  failedLoginAnimation();
                                }else{
                                  String token = e['token'];
                                  PostHTTP().sendRequestAPI(token, 'membership').then((value){
                                    if(value['status'] == "200"){
                                      String membership = value['membership'];
                                      print(membership);
                                      if(membership == "138" || membership == "136"){
                                        APIToken.token = token;
                                        JTools.saveLogin(token);
                                        print('User is premium ');
                                        FocusScope.of(context).requestFocus(new FocusNode());
                                        hasFinishedLogin = true;
                                        hasFinishLogAnim = false;
                                        hasFailedLogin = false;
                                        _playAnimationLogin();
                                      }else{
                                        print("User isn't premium ");
                                        Alerts(context: context).alertNotPremium();
                                        failedLoginAnimation();
                                      }
                                    }else{
                                      if(value['status'] == "404"){Alerts(context: context).alertErrorConnectionServer(); failedLoginAnimation();}
                                      if(value['status'] == "401" || value['status'] == "403"){Alerts(context: context).alertNotPremium(); failedLoginAnimation();}
                                    }
                                  });
                                }
                              });
                            }else{
                              Alerts(context: context).alertInternet();
                              failedLoginAnimation();
                            }
                          });


                          //Navigator.of(context).popAndPushNamed('/main');
                        },
                            buttonController:
                            _loginButtonController.view
                        ),

                        animationStatusFree == 0
                            ? new Padding(
                          padding: const EdgeInsets.only(bottom: 85.0),
                          child: new InkWell(
                              onTap: () {
                                setState(() {
                                  animationStatusFree = 1;
                                });
                                _playAnimationFree();
                              },
                              child: new FreeAccess()),
                        )
                            : new StaggerAnimationFree(
                            buttonController:
                            _freeButtonController.view),
                      ],
                    ),
                  ],
                ),
              ),
            )
        )
    );
  }

  Widget waitingPage(){
    return WillPopScope(child: Scaffold(backgroundColor: DesignColors.backgroundColor.withOpacity(1), body: Center(child: new CircularProgressIndicator(
      value: null,
      strokeWidth: 1.0,
      valueColor: new AlwaysStoppedAnimation<Color>(
          DesignColors.robot1Theme),
    )),), onWillPop:() async => false);
  }

  @override
  Widget build(BuildContext context) {
    timeDilation = 0.4;
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light);


    if(userLoginToken == null && tokenFileExist == 'false'){
      return logPage();
    }

    if(userLoginToken == null && tokenFileExist == null && backToLogin == "true"){
      //TODO: on loading
      backToLogin ="false";
      tokensManagement();
      return logPage();
    }else if(userLoginToken == null && tokenFileExist == null){
      //TODO: on loading
      return waitingPage();
    }

    if(userLoginToken.isNotEmpty && tokenFileExist == null){
      //TODO: on loading
      return waitingPage();
    }


    if(userLoginToken.isEmpty && tokenFileExist == 'true'){
      return logPage();
    }

    return logPage();
  }
}

Мой класс по анимации

import 'package:flutter/material.dart';
import 'package:test/premium/tools/design/color/designColors.dart';
import 'login.dart';

class StaggerAnimationSignIn extends StatelessWidget {
  final action;
  StaggerAnimationSignIn({Key key, this.buttonController, @required this.action})
      : buttonSqueezeanimation = new Tween(
          begin: 320.0,
          end: 70.0,
        )
            .animate(
          new CurvedAnimation(
            parent: buttonController,
            curve: new Interval(
              0.0,
              0.175,
            ),
          ),
        ),
        buttomZoomOut = new Tween(
          begin: 70.0,
          end: 5000.0,
        )
            .animate(
          new CurvedAnimation(
            parent: buttonController,
            curve: new Interval(
              0.55,
              0.999,
              curve: Curves.bounceOut,
            ),
          ),
        ),
        containerCircleAnimation = new EdgeInsetsTween(
          begin: const EdgeInsets.only(bottom: 160.0),
          end: const EdgeInsets.only(bottom: 0.0),
        )
            .animate(
          new CurvedAnimation(
            parent: buttonController,
            curve: new Interval(
              0.500,
              0.800,
              curve: Curves.ease,
            ),
          ),
        ),
        super(key: key);

  final AnimationController buttonController;
  final Animation<EdgeInsets> containerCircleAnimation;
  final Animation buttonSqueezeanimation;
  final Animation buttomZoomOut;

  Widget _buildAnimation(BuildContext context, Widget child) {
    return new Padding(
      padding: buttomZoomOut.value == 80
          ? const EdgeInsets.only(bottom: 160.0)
          : containerCircleAnimation.value,
      child: new InkWell(
          onTap: () {

          },
          child: new Hero(
            tag: "fadeLogin",
            child: buttomZoomOut.value <= 300
                ? new Container(
                    width: buttomZoomOut.value == 70
                        ? buttonSqueezeanimation.value
                        : buttomZoomOut.value,
                    height:
                        buttomZoomOut.value == 70 ? 60.0 : buttomZoomOut.value,
                    alignment: FractionalOffset.center,
                    decoration: new BoxDecoration(
                      color: DesignColors.animatedLoginColor,
                      borderRadius: buttomZoomOut.value < 400
                          ? new BorderRadius.all(const Radius.circular(30.0))
                          : new BorderRadius.all(const Radius.circular(0.0)),
                    ),
                    child: buttonSqueezeanimation.value > 75.0
                        ? new Text(
                            "Sign In",
                            style: new TextStyle(
                              color: Colors.white,
                              fontSize: 20.0,
                              fontWeight: FontWeight.w300,
                              letterSpacing: 0.3,
                            ),
                          )
                        : buttomZoomOut.value < 300.0
                            ? new CircularProgressIndicator(
                                value: null,
                                strokeWidth: 1.0,
                                valueColor: new AlwaysStoppedAnimation<Color>(
                                    Colors.white),
                              )
                            : null)
                : new Container(
                    width: buttomZoomOut.value,
                    height: buttomZoomOut.value,
                    decoration: new BoxDecoration(
                      shape: buttomZoomOut.value < 500
                          ? BoxShape.circle
                          : BoxShape.rectangle,
                      color: DesignColors.animatedLoginColor,
                    ),
                  ),
          )),
    );
  }


  @override
  Widget build(BuildContext context) {
      if(LoginScreenState.isFirstCallAction){
        buttonController.addListener(() {
            if (LoginScreenState.isFirstCallAction) {
              print("1");
              LoginScreenState.isFirstCallAction = false;
              action();
            }

            if (LoginScreenState.hasFailedLogin) {
              print("3");
              LoginScreenState.hasFailedLogin = false;
              buttonController.reverse();
              LoginScreenState.animationStatusLogin = 0;
            }

            if (buttonController.value > 0.2 &&
                LoginScreenState.hasFinishedLogin == false &&
                LoginScreenState.hasFailedLogin == false &&
                LoginScreenState.hasFinishLogAnim == false) {
              print("2");
              buttonController.stop();
            }

            if (LoginScreenState.hasFinishedLogin && !LoginScreenState.hasFailedLogin && !LoginScreenState.hasFinishLogAnim && buttonController.value == 1.0) {
              print("4");
              LoginScreenState.hasFinishedLogin = false;
              LoginScreenState.hasFailedLogin = false;
              LoginScreenState.hasFinishLogAnim = true;
              LoginScreenState.animationStatusLogin = 0;
              Navigator.popAndPushNamed(context, "/main");
              return;
          }
        });

    }
    return new AnimatedBuilder(
      builder: _buildAnimation,
      animation: buttonController,
    );
  }
}

Обновление :

HI я решил проблемы, которые я думаю,Мне все еще нужно выполнить несколько тестов, но кажется, что вызов Navigator.popAndPushNamed(context, "/main"); в AnimationClass не был хорошей идеей. Я просто изменил свой класс Login таким образом, чтобы после завершения анимации я вызывал Navigator.popAndPushNamed(context, "/main"); в своем классе login.я буду обновлять этот пост в ближайшие дни.

Новое начало в моем классе входа в систему сборки

      @override
  Widget build(BuildContext context) {
    _loginButtonController.addListener((){
      if(_loginButtonController.isCompleted){
        FocusScope.of(context).requestFocus(new FocusNode());
        Navigator.popAndPushNamed(context, "/main");
      }
    });

И удалены Navigator.popAndPushNamed(context, "/main"); и return; в Моей анимации конечного вызова

...