I'm trying to use isolates in my Flutter app with Bloc as a state management solution. Right now, I'm running into an error when running a particular function in wallet_list.dart
.
// wallet_list.dart
final FlutterSecureStorage _storage = const FlutterSecureStorage();
FutureOr<List<alan.Wallet>> getWalletList(int value) async {
Map<String, String> allValues = await _storage.readAll();
final List<alan.Wallet> _walletList = [];
allValues.forEach((key, value) {
if (key.startsWith(WalletOverviewHomeScreen.walletKey)) {
final arrMnemonic = value.split(' ');
final _wallet = alan.Wallet.derive(arrMnemonic, certikNetworkInfo);
// debugPrint('Adding wallet: $_wallet');
_walletList.add(_wallet);
}
});
The following function is used in one of the methods in the cubit class WalletInitializationCubit
.
// inside WalletInitializationCubit
Future<void> getWalletListAndDefaultWallet() async {
try {
debugPrint('WalletListInitialization');
emit(WalletInitializationLoading());
final List<alan.Wallet> walletList = await compute(
getWalletList,
1
);
// other cubit logic
}
When trying to build the app, it returns this error:
Exception has occurred.
_AssertionError ('package:flutter/src/services/platform_channel.dart': Failed assertion:
line 134 pos 7: '_binaryMessenger != null || ServicesBinding.instance != null': Cannot use
this MethodChannel before the binary messenger has been initialized. This happens when you
invoke platform methods before the WidgetsFlutterBinding has been initialized. You can fix
this by either calling WidgetsFlutterBinding.ensureInitialized() before this or by passing
a custom BinaryMessenger instance to MethodChannel().)
For context, the main.dart
file looks similar to this.
void main() async {
runApp(
const MyApp(),
);
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
const MyApp();
@override
Widget build(BuildContext context) {
final ThemeData theme = ThemeData();
return MultiBlocProvider(
providers: [
BlocProvider<WalletInitializationCubit>(
create: (context) => WalletInitializationCubit(),
),
],
child: HomeScreen(),
.....
}
}
The relevant line of code that causes the error is
// in getWalletList function
Map<String, String> allValues = await _storage.readAll();
I've tried adding WidgetsFlutterBinding.ensureInitialized()
before that line as so:
// in getWalletList function
WidgetsFlutterBinding.ensureInitialized()
Map<String, String> allValues = await _storage.readAll();
But that would then cause a UI actions are only available on root isolate
error.
How can I fix this error? I can't use the usual way of using async
and await
since the process being ran is rather heavy and causes the app to freeze.
CodePudding user response:
Based on the error UI actions are only available on root isolate
it is clear that you cannot execute WidgetsFlutterBinding.ensureInitialized()
inside the isolate. Also, as you mentioned in the comments, _storage.readAll()
method causes this problem.
Having this in mind, what you could do is run the _storage.readAll()
in your main isolate (what's run by the main function) and pass the result to the isolate as a parameter.