计时器不会取消 - 颤振提供程序



我的应用程序的目标是当我点击start按钮时,计时器应该启动,每5秒运行一个功能,当stopped计时器应该取消并停止该功能运行。(现在我有不同的屏幕为同一目的,所以我做了一个共同的屏幕,现在我发送一个Timer定时器到共同的有状态类构造函数)。所以,问题是,计时器不会取消,当我点击start时,函数每5秒执行一次,但不会停止。下面我为我的查询提供了一些相关的代码片段。

主屏幕:

class StrategyOneScreen extends StatefulWidget {
const StrategyOneScreen({Key? key}) : super(key: key);
@override
State<StrategyOneScreen> createState() => _StrategyOneScreenState();
}
class _StrategyOneScreenState extends State<StrategyOneScreen> {
@override
Widget build(BuildContext context) {
Timer timer1 = Timer(Duration(), () {});
return StrategyScreen(
stratName: 'Free Strategy',
timer: timer1,
toggle: Provider.of<StrategyProvider>(
context,
listen: true,
).companyStratOneToggle,
toggleTimer: Provider.of<StrategyProvider>(
context,
listen: false,
).toggleCompanyTimer,
setToggle: Provider.of<StrategyProvider>(
context,
listen: false,
).setCompanyStratOneToggle,
chartLiveData: Provider.of<StrategyProvider>(
context,
listen: true,
).companyChartLiveData,
);
}
}

通用StrategyScreen:

class StrategyScreen extends StatefulWidget {
const StrategyScreen({
Key? key,
required this.stratName,
required this.timer,
required this.toggle,
required this.toggleTimer,
required this.setToggle,
required this.chartLiveData,
}) : super(key: key);
final stratName;
final timer;
final toggle;
final toggleTimer;
final setToggle;
final chartLiveData;
@override
_StrategyScreenState createState() => _StrategyScreenState();
}
class _StrategyScreenState extends State<StrategyScreen> {
@override
Widget build(BuildContext context) {
print("Timer: ${widget.timer}"); // console logs:=> Timer: null
return Scaffold(
...
Row(
children: [
Expanded(
child: Center(
child: FloatingActionButton.extended(
heroTag: 'btn1',
onPressed: widget.toggle == false
? () => {
widget.toggleTimer(
ref,
showNotification('title', 'body'),
widget.timer,
widget.toggle,
),
widget.setToggle(),
}
: null,
label: Text('Start'),
icon: Icon(Icons.launch),
backgroundColor: Colors.greenAccent,
),
),
),
Expanded(
child: Center(
child: FloatingActionButton.extended(
heroTag: 'btn2',
onPressed: widget.toggle
? () => {
widget.toggleTimer(
ref,
showNotification('title', 'body'),
widget.timer,
widget.toggle,
),
widget.setToggle(),
}
: null,
label: Text('Stop'),
icon: Icon(Icons.stop),
backgroundColor: Colors.pink,
),
),
),
],
),

StrategyProvider.dart:

class StrategyProvider with ChangeNotifier {
// Toggles
bool _companyStratOneToggle = false;
bool get companyStratOneToggle => _companyStratOneToggle;
ChartLiveData _companyChartLiveData = ChartLiveData(
...
);
ChartLiveData get companyChartLiveData => _companyChartLiveData;

toggleCompanyTimer(ref, showNotification, timer, bool toggle) {
if (toggle == false) {
timer = Timer.periodic(
Duration(seconds: 5),
(Timer t) => {
fetchCompanyLiveStockData( // The function I want to run every 5 seconds
ref,
showNotification,
),
},
);
} else {
timer.cancel();
print("Timer Canceled!");
}
}
// Toggle setters for different strategies
setCompanyStratOneToggle() {
_companyStratOneToggle = !_companyStratOneToggle;
notifyListeners();
}
}

所以,正如我之前所说,我能够启动定时器,但不能取消它(因为它是null),它保持每5秒运行一次。下面是控制台输出:

Unhandled Exception: NoSuchMethodError: Class 'Future<dynamic>' has no instance method 'call'.
E/flutter ( 2746): Receiver: Instance of 'Future<dynamic>'
E/flutter ( 2746): <asynchronous suspension>
E/flutter ( 2746):
I/flutter ( 2746): Timer: null

当我按下cancel按钮时:

The following NoSuchMethodError was thrown while handling a gesture:
The method 'cancel' was called on null.
Receiver: null
Tried calling: cancel()
When the exception was thrown, this was the stack
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:63:5)
#1      StrategyProvider.toggleSbinTimer
package:myapp/…/global/strategy_provider.dart:67
#2      _StrategyScreenState.build.<anonymous closure>
package:myapp/…/global/strategy_screen.dart:152

最终您的问题是,您试图在toggleCompanyTimer中构建Timer对象,并试图在调用者中分配对该对象的引用。然而,Dart是不是按引用传递的,所以toggleCompanyTimer没有直接的方法来做到这一点。

如果你的StrategyProvider类完全自己拥有和管理Timer对象,情况会好得多。例如:

class StrategyProvider with ChangeNotifier {
Timer? timer;
// ... Other code...
void toggleCompanyTimer(ref, showNotification, bool stopTimer) {
// Cancel any existing Timer before creating a new one.
timer?.cancel();
timer = null;
if (!stopTimer) {
timer = Timer.periodic(
Duration(seconds: 5),
(Timer t) => {
fetchCompanyLiveStockData(
ref,
showNotification,
),
},
);
} else {
print("Timer Canceled!");
}
}
}

相关内容

  • 没有找到相关文章

最新更新