美文网首页
iOS原生使用FlutterEngineGroup接入flutt

iOS原生使用FlutterEngineGroup接入flutt

作者: 晨曦中的花豹 | 来源:发表于2024-04-06 13:43 被阅读0次

    原生项目集成flutter流程这里不做说明
    FlutterEngineGroup在推出后,很好的解决了原生跳转多flutter页面的路由问题,可以非常容易的实现native->flutter->native->flutter这种嵌套路由,只需要重新创建一个flutterEngine,并且开销很小

    1. 创建FlutterEngineGroup

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        self.flutterEngineGroup = [[FlutterEngineGroup alloc] initWithName:@"flutterGroupName" project:nil];
        return [super application:application didFinishLaunchingWithOptions:launchOptions];
    }
    

    2. 创建FlutterViewController

    @interface MyFlutterViewController : FlutterViewController
    
    -(instancetype)initWithFlutterUrl:(NSString *)url;
    
    @end
    
    @implementation MyFlutterViewController
    
    -(instancetype)initWithFlutterUrl:(NSString *)url {
        FlutterEngineGroup *engineGroup = [AppDelegate getFlutterEngineGroup];
        FlutterEngine *engine = [engineGroup makeEngineWithEntrypoint:nil libraryURI:nil initialRoute:url];
        return [self initWithEngine:engine nibName:nil bundle:nil];
    }
    @end
    

    这样就实现了多engine的路由跳转
    但是FlutterEngineGroup一个弊端就是EngineEngine之间数据是隔离的,没有办法直接通信,这里我采用原生平台作为中转站,通过channel先通知原生平台,再由原生平台来通知到其他的flutterEngine
    首先要说明的是因为flutterEngine是相互隔离的,所以注册的channel也是隔离的

    3. 创建Engine-Channel键值对管理类

    把目前还在路由栈中的engine以及对应的channel对应保存起来,这里我使用NSMapTable,原因是NSMapTablekey不需要遵守NSCopying协议,并且可以设置keyValue的引用类型,当设置为weak引用,当engine销毁后,对应的键值对会自动回收
    先创建一个flutterManage用来管理Engine-Channel键值对,作为一个单例,提供添加以及遍历通知的方法

    @interface FlutterManage : NSObject
    
    + (instancetype)shared;
    
    - (void)setObject:(FlutterMethodChannel *)anObject forKey:(FlutterEngine *)aKey;
    
    -(void)notifyOtherFlutterEngineWithEngine:(FlutterEngine *)engine info:(id)info;
    
    @end
    
    static FlutterManage *_manage = nil;
    
    @interface FlutterManage ()
    
    @property(nonatomic, strong) NSMapTable<FlutterEngine *,FlutterMethodChannel *> *table;
    
    @end
    
    @implementation FlutterManage
    
    + (instancetype)shared {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _manage = [[self alloc] init];
            _manage.table = [NSMapTable weakToWeakObjectsMapTable];
        });
        return _manage;
    }
    
    -(void)setObject:(FlutterMethodChannel *)anObject forKey:(FlutterEngine *)aKey {
        [_table setObject:anObject forKey:aKey];
    }
    
    -(void)notifyOtherFlutterEngineWithEngine:(FlutterEngine *)engine info:(id)info {
        FlutterMethodChannel *channel = [_manage.table objectForKey:engine];
        NSEnumerator *enumerator = [_manage.table objectEnumerator];
        FlutterMethodChannel *target;
        while (target = [enumerator nextObject]) {
            if (target == channel) continue;;
            [target invokeMethod:@"notifyOtherFlutterEngine" arguments:info];
        }
    }
    @end
    

    4. 在MyFlutterViewController中保存engine-channel键值对,并且在收到通知消息notifyOtherFlutterEngine后调用管理类的通知方法

    -(void)initChannel {
        __weak typeof(self) weakSelf = self;
        self.methodChannel = [FlutterMethodChannel methodChannelWithName:@"my_methodChannel" binaryMessenger:self.binaryMessenger];
            [self.methodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult  _Nonnull result) {
                if ([call.method isEqualToString:@"notifyOtherFlutterEngine"]) {
                    [[FlutterManage shared] notifyOtherFlutterEngineWithEngine:weakSelf.engine info:call.arguments];
                }
            }];
        [FlutterManage.shared setObject:self.methodChannel forKey:self.engine];
    }
    

    到此,实现了多引擎之间的数据传递
    我觉得通道有这一个就可以了,后面如果需要细分不同的通知做不一样的逻辑,我们可以再info中扩展参数,这样就不必每次有新的通知类型,都去修改FlutterManage这个类,扩展只限制在业务层

    相关文章

      网友评论

          本文标题:iOS原生使用FlutterEngineGroup接入flutt

          本文链接:https://www.haomeiwen.com/subject/ogvatjtx.html