英文:
Flutter Isolates: The BackgroundIsolateBinaryMessenger.instance value is invalid until BackgroundIsolateBinaryMessenger.ensureInitialized is executed
问题
在我的Flutter应用程序上运行Android API28模拟器时,启动Isolate会导致应用程序崩溃并显示以下错误:
[Bad state: The BackgroundIsolateBinaryMessenger.instance value is invalid until BackgroundIsolateBinaryMessenger.ensureInitialized is executed., #0 BackgroundIsolateBinaryMessenger.instance
_background_isolate_binary_messenger_io.dart:27
...
]
我已经在runApp(const MyApp());
之前运行了WidgetsFlutterBinding.ensureInitialized();
,这应该确保在应用程序开始运行之前BackgroundIsolateBinaryMessenger
已经初始化。
是否仍然需要运行BackgroundIsolateBinaryMessenger.ensureInitialized
,以及如何执行此操作?
英文:
On my Flutter app running on a Android API28 emulator, starting an Isolate will cause the app to crash with the error:
> [Bad state: The BackgroundIsolateBinaryMessenger.instance value is invalid until BackgroundIsolateBinaryMessenger.ensureInitialized is executed., #0 BackgroundIsolateBinaryMessenger.instance
Am already running WidgetsFlutterBinding.ensureInitialized();
before runApp(const MyApp());
, which should ensure that BackgroundIsolateBinaryMessenger
is already initialized before the app starts running.
Do we still have to run BackgroundIsolateBinaryMessenger.ensureInitialized
, and how do we do this?
import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:sensors_plus/sensors_plus.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
double _x = 0;
static void _isolateTask(SendPort sendPort) async {
debugPrint("Inside _isolateTask");
accelerometerEvents.listen((AccelerometerEvent event) {
debugPrint('_isolateTask x: $event.x');
sendPort.send(event.x);
});
}
void _startIsolate() async {
debugPrint("_startIsolate()");
var receivePort = ReceivePort();
await Isolate.spawn(_isolateTask, receivePort.sendPort);
receivePort.listen((dynamic message) {
setState(() {
_x = message;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'X: $_x',
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _startIsolate,
tooltip: 'Start Isolate',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
Full Trace
I/flutter ( 5071): _startIsolate()
I/flutter ( 5071): Inside _isolateTask
I/flutter ( 5071): error: [Bad state: The BackgroundIsolateBinaryMessenger.instance value is invalid until BackgroundIsolateBinaryMessenger.ensureInitialized is executed., #0 BackgroundIsolateBinaryMessenger.instance
_background_isolate_binary_messenger_io.dart:27
I/flutter ( 5071): #1 _findBinaryMessenger
platform_channel.dart:135
I/flutter ( 5071): #2 EventChannel.binaryMessenger
platform_channel.dart:629
I/flutter ( 5071): #3 EventChannel.receiveBroadcastStream.<anonymous closure>
platform_channel.dart:649
I/flutter ( 5071): #4 _runGuarded (dart:async/stream_controller.dart:814:24)
I/flutter ( 5071): #5 _BroadcastStreamController._subscribe (dart:async/broadcast_stream_controller.dart:207:7)
I/flutter ( 5071): #6 _ControllerStream._createSubscription (dart:async/stream_controller.dart:827:19)
I/flutter ( 5071): #7 _StreamImpl.listen (dart:async/stream_impl.dart:471:9)
I/flutter ( 5071): #8 new _ForwardingStreamSubscription (dart:async/stream_pipe.dart:114:10)
I/flutter ( 5071): #9 _ForwardingStream._createSubscription (dart:async/stream_pipe.dart:86:16)
I/flutter ( 5071): #10 _ForwardingStream.listen (dart:async/stream_pipe.dart:81:12)
I/flutter ( 5071): #11 _MyHomePageState._isolateTask
main.dart:44
I/flutter ( 5071): #12 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:300:17)
I/flutter ( 5071): #13 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:192:26)
I/flutter ( 5071): ]
Dependencies
dependencies:
flutter:
sdk: flutter
wear: ^1.1.0
sensors_plus: ^2.0.2
答案1
得分: 4
将令牌传递给孤立体。
顶级函数:
Future<dynamic> computeIsolate(Future Function() function) async {
final receivePort = ReceivePort();
var rootToken = RootIsolateToken.instance!;
await Isolate.spawn<_IsolateData>(
_isolateEntry,
_IsolateData(
token: rootToken,
function: function,
answerPort: receivePort.sendPort,
),
);
return await receivePort.first;
}
void _isolateEntry(_IsolateData isolateData) async {
BackgroundIsolateBinaryMessenger.ensureInitialized(isolateData.token);
final answer = await isolateData.function();
isolateData.answerPort.send(answer);
}
class _IsolateData {
final RootIsolateToken token;
final Function function;
final SendPort answerPort;
_IsolateData({
required this.token,
required this.function,
required this.answerPort,
});
}
要使用它:
var contacts = await computeIsolate(_getContacts);
// 确保静态函数在类内部
static Future<List<Contact>> _getContacts() async {
final contacts = await FlutterContacts.getContacts(withProperties: true);
return contacts;
}
英文:
Pass the token to the isolate.
Top-level function:
Future<dynamic> computeIsolate(Future Function() function) async {
final receivePort = ReceivePort();
var rootToken = RootIsolateToken.instance!;
await Isolate.spawn<_IsolateData>(
_isolateEntry,
_IsolateData(
token: rootToken,
function: function,
answerPort: receivePort.sendPort,
),
);
return await receivePort.first;
}
void _isolateEntry(_IsolateData isolateData) async {
BackgroundIsolateBinaryMessenger.ensureInitialized(isolateData.token);
final answer = await isolateData.function();
isolateData.answerPort.send(answer);
}
class _IsolateData {
final RootIsolateToken token;
final Function function;
final SendPort answerPort;
_IsolateData({
required this.token,
required this.function,
required this.answerPort,
});
}
To use it:
var contacts = await computeIsolate(_getContacts);
// Make sure static function if inside class
static Future<List<Contact>> _getContacts() async {
final contacts = await FlutterContacts.getContacts(withProperties: true);
return contacts;
}
答案2
得分: 2
在隔离的顶部添加 BackgroundIsolateBinaryMessenger.ensureInitialized。
RootIsolateToken rootIsolateToken = RootIsolateToken.instance!;
void _isolateTask(SendPort sendPort) async {
debugPrint("Inside _isolateTask");
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
accelerometerEvents.listen((AccelerometerEvent event) {
debugPrint('_isolateTask x: $event.x');
sendPort.send(event.x);
});
}
英文:
Add BackgroundIsolateBinaryMessenger.ensureInitialized at top of isolate.
RootIsolateToken rootIsolateToken = RootIsolateToken.instance!;
void _isolateTask(SendPort sendPort) async {
debugPrint("Inside _isolateTask");
BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
accelerometerEvents.listen((AccelerometerEvent event) {
debugPrint('_isolateTask x: $event.x');
sendPort.send(event.x);
});
}
答案3
得分: 0
在我的情况下,我是在按钮中调用compute
,所以我只需要在按钮中添加获取RootIsolate
实例的调用。
GestureDetector(
onTap: () async {
final token = RootIsolateToken.instance;
final result = await compute(functionName, token);
}
}
dynamic functionName(dynamic token){
BackgroundIsolateBinaryMessenger.ensureInitialized(token);
//代码的其余部分。
}
英文:
In my case i was calling the compute in a button so all i had to do was put the call to get the instance of the RootIsolate in the button
GestureDetector(
onTap: () {
final token = RootIsolateToken.instance;
final result = await compute(functionName,token);
}
}
dynamic functionName(dynamic token){
BackgroundIsolateBinaryMessenger.ensureInitialized(token);
//Rest of code.
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论