一旦视图更改,颤动数字时钟小部件就会导致错误

Posted

技术标签:

【中文标题】一旦视图更改,颤动数字时钟小部件就会导致错误【英文标题】:Flutter digital clock widget causing errors as soon as the view is changed 【发布时间】:2021-05-24 08:42:04 【问题描述】:

我正在使用https://pub.dev/packages/slide_digital_clock,它会导致内存泄漏和动画错误垃圾邮件,我不知道如何修复它,一旦视图被发送回注销,就会发生这种情况。如果有人能解释一下如何修复它,将不胜感激

import 'dart:convert';
import 'package:flutter/widgets.dart';
import 'package:attenv02/login_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:geolocator/geolocator.dart';
import 'package:slide_digital_clock/slide_digital_clock.dart';
import 'package:intl/intl.dart';

class HomePage extends StatefulWidget 
@override
_HomePageState createState() => _HomePageState();



class _HomePageState extends State<HomePage> 
 var locationMessege= "";
 bool timeinbtn = true;
 bool timeoutbtn = false;
 String name = "";

 void initState() 
 super.initState();
 

Future <String> loadPref()async
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
return Future.delayed(Duration(seconds: 1),()async
  return await sharedPreferences.getString("useFullName");
);




 logout()async
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.clear();
sharedPreferences.commit();
Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (BuildContext context) 
=> LoginPage()), (Route<dynamic> route) => false);



void getCurrentLocation()async
var position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
var lastPosition=await Geolocator.getLastKnownPosition();
String now =await new DateFormat.yMd().add_Hm().format(new DateTime.now());
timeinbtn=!timeinbtn;
timeoutbtn=!timeoutbtn;
print(lastPosition);
print(now);

setState(() 
  locationMessege="$position.latitude,$position.longitude,$now";
);


@override
Widget build(BuildContext context) 
return Scaffold(
  appBar: AppBar(
    backgroundColor:Color.fromRGBO(255, 191, 68, 1),
    title:FutureBuilder(
      future: loadPref(),
      builder: (context, snapshot) 
        if(snapshot.hasData)
          return Text("$snapshot.data");
        else
          return Text("Loading");
        
      ,
    ),
    actions: <Widget>[
      FlatButton(
        onPressed: () 
          logout();
        ,
        child: Text("Log Out", style: TextStyle(color: Colors.white)),
      ),
    ],
  ),
  body: Container(
    decoration: BoxDecoration(
        image: DecorationImage(
            image: AssetImage("assets/bg.jpg"), fit: BoxFit.cover)),
    child: Center(
      child: Container(
        padding: EdgeInsets.all(30),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [

            Column(
              children:<Widget>  [
                Container(
                    child:DigitalClock(
                      digitAnimationStyle: Curves.elasticOut,
                      is24HourTimeFormat: false,
                      areaDecoration: BoxDecoration(
                        color: Colors.transparent,
                      ),
                      hourMinuteDigitTextStyle: TextStyle(
                        color: Colors.blueGrey,
                        fontSize: 50,
                      ),
                      amPmDigitTextStyle: TextStyle(color: Colors.blueGrey, fontWeight: FontWeight.bold),
                    ),
                ),

                Text("Position:$locationMessege",style:TextStyle(
                    color: Colors.black,
                    fontSize: 10.0,
                    fontWeight: FontWeight.bold)),
                Visibility(
                  visible:timeinbtn,
                  child: FlatButton(onPressed:()
                    getCurrentLocation();
                  ,
                      color: Colors.orange,
                      child: Text("Time in",
                        style: TextStyle(
                          color: Colors.white,
                        ),)),
                ),
                Visibility(
                  visible: timeoutbtn,
                  child: FlatButton(onPressed:()
                    getCurrentLocation();
                  ,
                      color: Colors.orange,
                      child: Text("Time out",
                        style: TextStyle(
                          color: Colors.white,
                        ),)),
                )
              ],
            ),
          ],
        ),
      ),

    ),
  ),
);


在最终确定小部件树时引发了以下断言: _SpinnerTextState#321b2(ticker active) 与活动的 Ticker 一起处置。

_SpinnerTextState 通过其 SingleTickerProviderStateMixin 创建了一个 Ticker,但在 mixin 上调用 dispose() 时,该 Ticker 仍然处于活动状态。 Ticker 必须在调用 super.dispose() 之前被释放。

AnimationControllers 使用的代码应该通过调用 AnimationController 本身的 dispose() 来处理。否则,代码会泄露。

动画库捕获的异常 在通知 AnimationController 的侦听器时引发了以下断言: 'package:flutter/src/widgets/framework.dart':断言失败:第 4109 行 pos 12:'_lifecycleState != _ElementLifecycle.defunct':不正确。

动画库捕获的异常 'package:flutter/src/widgets/framework.dart':断言失败:第 4109 行 pos 12:'_lifecycleState != _ElementLifecycle.defunct':不正确。

动画库捕获的异常 'package:flutter/src/widgets/framework.dart':断言失败:第 4109 行 pos 12:'_lifecycleState != _ElementLifecycle.defunct':不正确。

【问题讨论】:

【参考方案1】:

这个包有两个错误,有两个拉取请求来修复这些问题,但是你必须手动合并它们,因为这两个拉取请求没有被所有者合并 第一步:更新lib/helpers/spinner_text.darthttps://github.com/caglarylmz/slide_digital_clock/pull/4/files/23cd40ac4f32fc7adeab4101af498994d40d43fd 从改变

  @override
  void dispose() 
    super.dispose();
    _spinTextAnimationController.dispose();
  

  @override
  void dispose() 
    _spinTextAnimationController.dispose();
    super.dispose();        
  

第二步:取消定时器,更新类_DigitalClockStatehttps://github.com/caglarylmz/slide_digital_clock/pull/1/commits/5a648954e83e8215180e05db5bbf9e232e4d385a 代码sn-p

Timer _timer;
...
_timer = Timer.periodic(Duration(seconds: 1), (timer) 
...
  @override
  void dispose() 
    _timer.cancel();
    super.dispose();
  

手动合并这两个拉取请求后的工作演示

工作演示的完整代码

import 'package:flutter/material.dart';
import 'package:slide_digital_clock/slide_digital_clock.dart';

void main() 
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  


class HomePage extends StatefulWidget 
  @override
  _HomePageState createState() => _HomePageState();


class _HomePageState extends State<HomePage> 
  var locationMessege = "";
  bool timeinbtn = true;
  bool timeoutbtn = false;
  String name = "";

  void initState() 
    super.initState();
  

  Future<String> loadPref() async 
    /*SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
    return Future.delayed(Duration(seconds: 1), () async 
      return await sharedPreferences.getString("useFullName");
    );*/

    return Future.value("useFullName");
  

  logout() async 
    Navigator.of(context).pushAndRemoveUntil(
        MaterialPageRoute(builder: (BuildContext context) => LoginPage()),
        (Route<dynamic> route) => false);
  

  void getCurrentLocation() async 
    /*var position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);
    var lastPosition = await Geolocator.getLastKnownPosition();
    String now = await new DateFormat.yMd().add_Hm().format(new DateTime.now());
    timeinbtn = !timeinbtn;
    timeoutbtn = !timeoutbtn;
    print(lastPosition);
    print(now);

    setState(() 
      locationMessege = "$position.latitude,$position.longitude,$now";
    );*/
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Color.fromRGBO(255, 191, 68, 1),
        title: FutureBuilder(
          future: loadPref(),
          builder: (context, snapshot) 
            if (snapshot.hasData) 
              return Text("$snapshot.data");
             else 
              return Text("Loading");
            
          ,
        ),
        actions: <Widget>[
          FlatButton(
            onPressed: () 
              logout();
            ,
            child: Text("Log Out", style: TextStyle(color: Colors.white)),
          ),
        ],
      ),
      body: Container(
        /*decoration: BoxDecoration(
            image: DecorationImage(
                image: NetworkImage("https://picsum.photos/250?image=9"),
                fit: BoxFit.cover)),*/
        child: Center(
          child: Container(
            padding: EdgeInsets.all(30),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Column(
                  children: <Widget>[
                    Container(
                      child: DigitalClock(
                        digitAnimationStyle: Curves.elasticOut,
                        is24HourTimeFormat: false,
                        areaDecoration: BoxDecoration(
                          color: Colors.transparent,
                        ),
                        hourMinuteDigitTextStyle: TextStyle(
                          color: Colors.blueGrey,
                          fontSize: 50,
                        ),
                        amPmDigitTextStyle: TextStyle(
                            color: Colors.blueGrey,
                            fontWeight: FontWeight.bold),
                      ),
                    ),
                    Text("Position:$locationMessege",
                        style: TextStyle(
                            color: Colors.black,
                            fontSize: 10.0,
                            fontWeight: FontWeight.bold)),
                    Visibility(
                      visible: timeinbtn,
                      child: FlatButton(
                          onPressed: () 
                            getCurrentLocation();
                          ,
                          color: Colors.orange,
                          child: Text(
                            "Time in",
                            style: TextStyle(
                              color: Colors.white,
                            ),
                          )),
                    ),
                    Visibility(
                      visible: timeoutbtn,
                      child: FlatButton(
                          onPressed: () 
                            getCurrentLocation();
                          ,
                          color: Colors.orange,
                          child: Text(
                            "Time out",
                            style: TextStyle(
                              color: Colors.white,
                            ),
                          )),
                    )
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  


class LoginPage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return Scaffold(body: Center(child: Text("Login Page")));
  

【讨论】:

如果这是一个愚蠢的问题,请道歉,但我是否需要创建文件或查找包文件,我的 lib 文件夹中没有 lib/helpers/spinner_text.dart 文件包含的主库我的应用飞镖 您可以将github中的所有代码复制粘贴到您的项目中,然后进行修改。或者直接 fork 这个 github 项目。 很高兴为您提供帮助。如果对您有帮助,请将其标记为答案。谢谢。 我在哪里复制它,我需要创建一个新的飞镖作为 lib/helpers/spinner_text.dart 吗?我在哪里可以找到这个 spinner_text.dart ? 是的。您可以复制所有文件并按照所有者的目录github.com/caglarylmz/slide_digital_clock/tree/master/lib 到您的项目中

以上是关于一旦视图更改,颤动数字时钟小部件就会导致错误的主要内容,如果未能解决你的问题,请参考以下文章

动态更改小部件的文本颤动/飞镖

JQuery 移动面板小部件 - 打开可折叠列表会导致一旦展开超出页面高度,就会跳转到页面 div 的底部。为啥?

在颤动中显示全屏加载小部件

如何遍历地图列表并在颤动列表视图中显示文本小部件?

如何在颤动中更改容器小部件中的背景图像

在文本小部件中为不同的字母颤动不同的颜色