I'm new to flutter and I just learned how to use isolates in Dart. When I try to access shared preference via an isolate it throws the given below error. This error also appears when I try to access Firebase analytics and remote config. How can I resolve this issue and access SharedPreference, FirebaseRemote config, FirebaseFirestore inside an isolate?
[ERROR:flutter/runtime/dart_isolate.cc(882)] Unhandled exception:
E/flutter (23694): ServicesBinding.defaultBinaryMessenger was accessed before the binding was initialized.
E/flutter (23694): If you're running an application and need to access the binary messenger before `runApp()` has been called (for example, during plugin initialization), then you need to explicitly call the `WidgetsFlutterBinding.ensureInitialized()` first.
E/flutter (23694): If you're running a test, you can call the `TestWidgetsFlutterBinding.ensureInitialized()` as the first line in your test's `main()` method to initialize the binding.
E/flutter (23694): #0 defaultBinaryMessenger.<anonymous closure> (package:flutter/src/services/binary_messenger.dart:92:7)
E/flutter (23694): #1 defaultBinaryMessenger (package:flutter/src/services/binary_messenger.dart:105:4)
E/flutter (23694): #2 MethodChannel.binaryMessenger (package:flutter/src/services/platform_channel.dart:143:62)
E/flutter (23694): #3 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:149:36)
E/flutter (23694): #4 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:332:12)
E/flutter (23694): #5 MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart:359:49)
E/flutter (23694): #6 MethodChannelSharedPreferencesStore.getAll (package:shared_preferences_platform_interface/method_channel_shared_preferences.dart:54:22)
E/flutter (23694): #7 SharedPreferences._getSharedPreferencesMap (package:shared_preferences/shared_preferences.dart:191:57)
E/flutter (23694): #8 SharedPreferences.getInstance (package:shared_preferences/shared_preferences.dart:58:19)
E/flutter (23694): #9 _wraperState.islt (package:spynett/main.dart:122:55)
E/flutter (23694): <asynchronous suspension>
E/flutter (23694): #10 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:304:17)
E/flutter (23694): #11 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await setupLocator();
runApp(MyApp());
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
startinitsetup();
});
}
Future startinitsetup() async{
debugPrint('Calling setup');
await _dynamiclink.handledynamiclink();
await _pushNotificationService.initilalise();
await _remoteConfigService.initialise();
ReceivePort reciveport = ReceivePort();
Isolate.spawn(islt, reciveport.sendPort);
SendPort childSendPort = await reciveport.first;
ReceivePort responceport = ReceivePort();
childSendPort.send(['message',responceport.sendPort]);
await responceport.first;
}
static Future<int> islt(SendPort mainSendPort) async{
ReceivePort childRecivePort = ReceivePort();
mainSendPort.send(childRecivePort.sendPort);
await for (var message in childRecivePort){
SendPort replyport = message[1];
SharedPreferences _pref = await SharedPreferences.getInstance();
replyport.send('done');
}
}
You can copy paste run full code below
To use SharedPreferences
in Isolate
, you can use package https://pub.dev/packages/flutter_isolate
You can change from
Isolate.spawn(islt, reciveport.sendPort);
to
FlutterIsolate.spawn(islt, reciveport.sendPort);
output of full test code
I/flutter (12689): Calling setup
...
I/flutter (12689): test test
I/flutter (12689): isolate when msg recived
I/flutter (12689): reply done
full test code
import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_isolate/flutter_isolate.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
//await Firebase.initializeApp();
//await setupLocator();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
startinitsetup();
});
}
Future startinitsetup() async {
debugPrint('Calling setup');
ReceivePort reciveport = ReceivePort();
FlutterIsolate.spawn(islt, reciveport.sendPort);
SendPort childSendPort = await reciveport.first;
ReceivePort responceport = ReceivePort();
childSendPort.send(['message', responceport.sendPort]);
String reply = await responceport.first;
print("reply $reply");
}
static Future<int> islt(SendPort mainSendPort) async {
ReceivePort childRecivePort = ReceivePort();
mainSendPort.send(childRecivePort.sendPort);
await for (var message in childRecivePort) {
SendPort replyport = message[1];
SharedPreferences _pref = await SharedPreferences.getInstance();
await _pref.setString("yourKey", "test");
String testPref = _pref.get("yourKey");
print("test $testPref");
debugPrint('isolate when msg recived');
replyport.send('done');
}
}
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}