Line data Source code
1 : import 'dart:async'; 2 : import 'dart:isolate'; 3 : 4 : import 'package:combine/src/bindings/isolate_bindings/isolate_binding.dart'; 5 : import 'package:combine/src/combine_info.dart'; 6 : import 'package:combine/src/combine_isolate/native_combine_isolate.dart'; 7 : import 'package:combine/src/isolate_context.dart'; 8 : import 'package:combine/src/isolate_factory/isolate_factory.dart'; 9 : import 'package:combine/src/isolate_messenger/internal_isolate_messenger/native_internal_isolate_messenger.dart'; 10 : import 'package:combine/src/method_channel_middleware/isolated_method_channel_middleware.dart'; 11 : import 'package:combine/src/method_channel_middleware/ui_method_channel_middleware.dart'; 12 : import 'package:flutter/services.dart'; 13 : 14 : /// It is used to create [Isolate] and setup all necessary stuff 15 : /// which is needed to use method channels. 16 : class NativeIsolateFactory extends IsolateFactory { 17 2 : @override 18 : Future<CombineInfo> create<T>( 19 : IsolateEntryPoint<T> entryPoint, { 20 : Map<String, Object?>? argumentsMap, 21 : T? argument, 22 : String? debugName, 23 : bool errorsAreFatal = true, 24 : }) async { 25 2 : final receivePort = ReceivePort(); 26 2 : final isolate = await Isolate.spawn<_IsolateSetup<T>>( 27 : _runInIsolate<T>, 28 2 : _IsolateSetup<T>( 29 2 : receivePort.sendPort, 30 : entryPoint, 31 : argumentsMap, 32 : argument, 33 : ), 34 : debugName: debugName, 35 : errorsAreFatal: errorsAreFatal, 36 : ); 37 : 38 4 : final receivePortStream = receivePort.asBroadcastStream().cast<Object?>(); 39 2 : final sendPort = await receivePortStream.first as SendPort; 40 : 41 2 : final isolateMessenger = NativeInternalIsolateMessenger( 42 : sendPort, 43 : receivePortStream, 44 : ); 45 : 46 2 : final methodChannelMiddleware = UIMethodChannelMiddleware( 47 4 : ServicesBinding.instance.defaultBinaryMessenger, 48 : isolateMessenger, 49 2 : )..initialize(); 50 2 : return CombineInfo( 51 2 : isolate: NativeCombineIsolate( 52 : isolate, 53 2 : () { 54 2 : methodChannelMiddleware.dispose(); 55 2 : isolateMessenger.markAsClosed(); 56 : }, 57 : ), 58 2 : messenger: isolateMessenger.toIsolateMessenger(), 59 : ); 60 : } 61 : 62 2 : static void _runInIsolate<T>(_IsolateSetup<T> setup) { 63 2 : final receivePort = ReceivePort(); 64 2 : final isolateMessenger = NativeInternalIsolateMessenger( 65 2 : setup.sendPort, 66 4 : receivePort.asBroadcastStream().cast<Object?>(), 67 : ); 68 4 : isolateMessenger.send(receivePort.sendPort); 69 : 70 2 : final isolateContext = IsolateContext( 71 2 : argument: setup.argument, 72 2 : messenger: isolateMessenger.toIsolateMessenger(), 73 4 : isolate: NativeCombineIsolate(Isolate.current, () {}), 74 : ); 75 : 76 4 : IsolatedMethodChannelMiddleware(isolateMessenger).initialize(); 77 2 : IsolateBinding(); 78 4 : setup.entryPoint(isolateContext); 79 : } 80 : } 81 : 82 : class _IsolateSetup<T> { 83 2 : _IsolateSetup( 84 : this.sendPort, 85 : this.entryPoint, 86 : this.argumentsMap, 87 : this.argument, 88 : ); 89 : 90 : final SendPort sendPort; 91 : final IsolateEntryPoint<T> entryPoint; 92 : final Map<String, Object?>? argumentsMap; 93 : final T? argument; 94 : } 95 : 96 : /// This typedef is used for conditional import. 97 : typedef IsolateFactoryImpl = NativeIsolateFactory;