Flutter应用冻结并且无法按预期工作
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter应用冻结并且无法按预期工作相关的知识,希望对你有一定的参考价值。
我有一个扑动的应用程序,有2页。第一页是一个简单的InkWell,它将用户发送到第2页。当点击第2页时,计时器应该每秒递减一次。它冻结而不是开始增量。
import 'package:flutter/material.dart';
import 'dart:io';
int _time = 60;
bool _restart = false;
class MainPage extends StatefulWidget {
@override
MainPageState createState() => new MainPageState();
}
class MainPageState extends State<MainPage> {
@override
Widget build(BuildContext context) {
return new Material(
color: Colors.greenAccent,
child: new InkWell(
onTap: () {
setState((){
while ( true ) {
sleep(const Duration(seconds:1));
_time = _time - 1;
}
});
},
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(_time.toString(), style: new TextStyle(color:
Colors.white, fontSize: 60.0, fontWeight: FontWeight.bold)),
]
),
),
);
}
}
答案
那是因为你处于无限循环中,更好的方法是使用Timer:
class TimerSample extends StatefulWidget {
@override
_TimerSampleState createState() => _TimerSampleState();
}
class _TimerSampleState extends State<TimerSample> {
int _time = 60;
bool _restart = false;
Timer timer;
_onTap() {
if (timer == null) {
timer = Timer.periodic(Duration(seconds: 1), (Timer t) {
_time = _time - 1;
//your conditions here
//call setState if you want to refresh the content
});
}
}
@override
void dispose() {
if (timer != null) {
timer.cancel();
}
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Material(
color: Colors.greenAccent,
child: new InkWell(
onTap: _onTap,
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(_time.toString(),
style: new TextStyle(
color: Colors.white,
fontSize: 60.0,
fontWeight: FontWeight.bold)),
]),
),
);
}
}
另一答案
来自睡眠文档
请谨慎使用,因为隔离区在睡眠调用中被阻止时,不能处理异步操作。
你不应该在setState中有逻辑,它应该只用于改变值。
据我所知,你想要启动一个计时器,每隔几秒就更新一次。
我会这样做的
Timer _timer;
...
_timer ??= new Timer.periodic(const Duration(seconds:1), () {
setState(() {
_time = _time - 1;
});
})
...
dispose() {
super.dispose();
_timer?.cancel();
}
另一答案
使用AnimatedBuilder
避免必须调用setState
来更新计数器文本。否则,您可能最终会不必要地重建小部件以更新动画。
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
int _startTime = 10;
Duration _totalTime;
AnimationController _controller;
@override
void initState() {
_totalTime = Duration(seconds: _startTime);
_controller = AnimationController(
vsync: this,
duration: _totalTime,
);
super.initState();
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
return Material(
color: Colors.greenAccent,
child: InkWell(
onTap: () {
if (_timeLeft().inMicroseconds == 0) {
_controller.reset();
} else {
if (!_controller.isAnimating) {
_controller.forward();
} else {
_controller.stop(canceled: false);
}
}
},
child: AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget child) {
return Center(
child: Text(
'${_timeLeft().inSeconds}',
style: TextStyle(
fontSize: 60.0,
color: Colors.white,
fontWeight: FontWeight.bold,
),
));
},
),
),
);
}
Duration _timeLeft() {
final timeLeft = _totalTime - (_totalTime * _controller.value);
if (timeLeft.inMicroseconds == 0 || timeLeft == _totalTime) {
return timeLeft;
} else {
return timeLeft + const Duration(seconds: 1);
}
}
}
另一答案
这是秒表的示例代码。
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _count = 0;
bool _flag1 = false;
bool _flag2 = false;
void _startCounter() {
_flag1 = true;
if (!_flag2) {
_flag2 = true;
Timer.periodic(Duration(milliseconds: 1000), (Timer timer) {
setState(() {
if (_flag1) _count++;
});
});
}
}
void _stopCounter() {
_flag1 = false;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Stopwatch"),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RaisedButton(
onPressed: _startCounter,
child: Text("Start"),
),
Text(_count.toString()),
RaisedButton(
onPressed: _stopCounter,
child: Text("Stop"),
),
],
),
),
);
}
}
以上是关于Flutter应用冻结并且无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章
Flutter 嵌套小部件 setState 无法按预期工作
Flutter - 使用提供程序时 whenComplete() 无法按预期工作