Flutter中background_locator_2插件Android端跨Isolate传LocationDto报错
问题与解决方案:background_locator_2 Android端隔离间通信错误
问题概述
使用background_locator_2(版本2.0.6-dev.2)实现后台位置获取功能,iOS端运行正常,但在Flutter和Kotlin版本更新后,Android端出现隔离间通信错误,错误信息如下:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Invalid argument: is a regular instance: Instance of 'LocationDto' E/flutter (26006): #0 _SendPort._sendInternal (dart:isolate-patch/isolate_patch.dart:249:43) E/flutter (26006): #1 _SendPort.send (dart:isolate-patch/isolate_patch.dart:230:5) E/flutter (26006): #2 LocationServiceRepository.callback package:drivers_app/tabPages/location_service_reposirtory.dart:59
错误指向LocationServiceRepository类中send?.send(locationDto);一行,原因是Dart隔离间仅支持传递可序列化对象(基本类型、List、Map或实现序列化协议的类),而LocationDto是普通实例,无法直接跨隔离间传递。
解决方案
方案1:将LocationDto转换为Map传递
修改LocationServiceRepository的callback方法,把LocationDto转为Map后发送,接收端再重建对象:
@pragma('vm:entry-point') Future<void> callback(LocationDto locationDto) async { print('$_count location in dart: ${locationDto.toString()}'); await setLogPosition(_count, locationDto); final SendPort? send = IsolateNameServer.lookupPortByName(isolateName); // 转换LocationDto为Map final locationMap = { 'latitude': locationDto.latitude, 'longitude': locationDto.longitude, 'accuracy': locationDto.accuracy, 'altitude': locationDto.altitude, 'speed': locationDto.speed, 'speedAccuracy': locationDto.speedAccuracy, 'heading': locationDto.heading, 'time': locationDto.time, 'isMocked': locationDto.isMocked, }; send?.send(locationMap); // 发送Map替代原对象 _count++; }
接收端updateUI方法重建LocationDto:
Future<void> updateUI(dynamic data) async { if (data is Map) { final locationDto = LocationDto( latitude: data['latitude'], longitude: data['longitude'], accuracy: data['accuracy'], altitude: data['altitude'], speed: data['speed'], speedAccuracy: data['speedAccuracy'], heading: data['heading'], time: data['time'], isMocked: data['isMocked'], ); await _updateNotificationText(locationDto); } }
方案2:让LocationDto实现序列化
通过json_serializable包让LocationDto支持序列化,适用于需要完整传递对象的场景:
- 依赖配置(
pubspec.yaml):
dependencies: json_annotation: ^4.8.1 dev_dependencies: build_runner: ^2.4.4 json_serializable: ^6.7.0
- 修改
LocationDto类(若为插件类,可复制到本地修改):
import 'package:json_annotation/json_annotation.dart'; part 'location_dto.g.dart'; @JsonSerializable() class LocationDto { final double latitude; final double longitude; final double accuracy; final double altitude; final double speed; final double speedAccuracy; final double heading; final int time; final bool isMocked; LocationDto({ required this.latitude, required this.longitude, required this.accuracy, required this.altitude, required this.speed, required this.speedAccuracy, required this.heading, required this.time, required this.isMocked, }); factory LocationDto.fromJson(Map<String, dynamic> json) => _$LocationDtoFromJson(json); Map<String, dynamic> toJson() => _$LocationDtoToJson(this); }
- 生成序列化代码:
flutter pub run build_runner build
- 修改发送和接收逻辑:
// 发送端 send?.send(locationDto.toJson()); // 接收端 Future<void> updateUI(dynamic data) async { if (data is Map) { final locationDto = LocationDto.fromJson(data.cast<String, dynamic>()); await _updateNotificationText(locationDto); } }
方案3:仅传递所需字段
若仅需部分字段(如经纬度),可直接传递单个字段或精简Map:
// 发送端 send?.send({ 'lat': locationDto.latitude, 'lng': locationDto.longitude, }); // 接收端 Future<void> updateUI(dynamic data) async { if (data is Map) { await BackgroundLocator.updateNotificationText( title: "Your location is updated", msg: "${DateTime.now()}", bigMsg: "${data['lat']}, ${data['lng']}", ); } }
内容的提问来源于stack exchange,提问作者Pannam
相关产品推荐
相关产品推荐

