I have the following Dart Isolate called in my Flutter app that runs and handles a task via the _checkTimer
method every 7 seconds. This is handy for background tasks that I need to run every certain period of time.
import 'dart:async';
import 'dart:isolate';
class TimeTrackingDigester with ChangeNotifier {
Isolate _isolate;
static int _counter = 0;
ReceivePort _receivePort;
void startIsolate() async {
print('**** time tracking digester = startIsolate');
_receivePort = ReceivePort();
_isolate = await Isolate.spawn(
_checkTimer,
_receivePort.sendPort,
);
_receivePort.listen(
_handleMessage,
onDone: () {
//@TODO this never fires
print('done!');
},
);
}
void stopIsolate() => _stop();
static void _checkTimer(SendPort sendPort) async {
print('**** time tracking digestoer = checkTimer');
Timer.periodic(
const Duration(seconds: 7),
(Timer t) async {
_counter++;
print('**** time tracking digestoer = $_counter');
var task = 'result from some action here';
sendPort.send(task);
},
);
}
void _handleMessage(dynamic data) {
print('**** time tracking digestoer = handleMessage');
print('RECEIVED: $data');
}
//@TODO this is not stopping the isolate
void _stop() {
print('**** time tracking digestoer = stop');
print(_isolate);
if (_isolate != null) {
print('* isolate is not null');
// setState(() {
// _running = false;
//
// });
_receivePort.close();
_isolate.kill(priority: Isolate.immediate);
_isolate = null;
}
}
}
My first problem is once the isolate is started, I call stopIsolate
method to stop the Isolate yet it doesn't ever hit the close()
/ kill()
calls because the _isolate
is considered null
. From what I can gather, the _isolate
is always null
and I'm missing a step to actually set the _isolate
in the following stanza:
if (_isolate != null) {
print('* isolate is not null');
// setState(() {
// _running = false;
//
// });
_receivePort.close();
_isolate.kill(priority: Isolate.immediate);
_isolate = null;
}
My second issue, is if I disregard the null check, and simply call the close()
/ kill()
methods, the following Exceptions are thrown:
NoSuchMethodError: The method 'close' was called on null. I/flutter (15558): Receiver: null I/flutter (15558): Tried calling: close()
The end result I am trying to accomplish: when I want to stop the Isolate, it fully stops the subsequent _checkTimer
method, and resolve the _isolate
from not being set correctly in order to trigger the null
check correctly.
I tested your code, and it can successfully stop the isolate. Please make sure that you're using the same instance of TimeTrackingDigester
so that _isolate
will not be null
.
Run this sample app.
import 'dart:async';
import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(fontFamily: 'Roboto'),
home: SampleIsolate(),
);
}
}
class SampleIsolate extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => TimeTrackingDigester(),
child: Builder(
builder: (context2) => Scaffold(
body: Center(
child: RaisedButton(
onPressed: () {
// Will get the TimeTrackingDigester created in "create: (_) => ..."
final digester = Provider.of<TimeTrackingDigester>(
context2,
listen: false,
);
if (digester.isStarted) {
digester.stopIsolate();
} else {
digester.startIsolate();
}
},
child: const Text('Start / Stop'),
),
),
),
),
);
}
}
class TimeTrackingDigester with ChangeNotifier {
Isolate _isolate;
static int _counter = 0;
ReceivePort _receivePort;
bool get isStarted => _isolate != null;
void startIsolate() async {
print('**** time tracking digester = startIsolate');
_receivePort = ReceivePort();
_isolate = await Isolate.spawn(
_checkTimer,
_receivePort.sendPort,
);
_receivePort.listen(
_handleMessage,
onDone: () {
//@TODO this never fires
print('done!');
},
);
}
void stopIsolate() => _stop();
static void _checkTimer(SendPort sendPort) async {
print('**** time tracking digestoer = checkTimer');
Timer.periodic(
const Duration(seconds: 7),
(Timer t) async {
_counter++;
print('**** time tracking digestoer = $_counter');
var task = 'result from some action here';
sendPort.send(task);
},
);
}
void _handleMessage(dynamic data) {
print('**** time tracking digestoer = handleMessage');
print('RECEIVED: $data');
}
//@TODO this is not stopping the isolate
void _stop() {
print('**** time tracking digestoer = stop');
print(_isolate);
if (_isolate != null) {
print('* isolate is not null');
// setState(() {
// _running = false;
//
// });
_receivePort.close();
_isolate.kill(priority: Isolate.immediate);
_isolate = null;
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.