native端完成(iOS

FlutterBasicMessageChannel channel通道

NSString * const FairMessageChannelExecuteID = @"com.wuba.fair/common_message_channel";  //
self.flutterBasicMessageChannel = [[FlutterBasicMessageChannel alloc] initWithName:FairMessageChannelExecuteID //运用FlutterBasicMessageChannel类型的channel通道
                                                                   binaryMessenger:self.binaryMessenger
                                                                             codec:[FlutterStringCodec sharedInstance]];

js调用dart,成果callback回调js

- (void)sendMessageToDart:(NSString *)message callback:(FairCallback)callback {
    [self.flutterBasicMessageChannel sendMessage:message reply:^(id reply) { //调用dart
        if (callback && FAIR_IS_NOT_EMPTY_STRING(reply)) {//dart回来成果,调用callback
            callback(reply, nil);
        }
    }];
}
- (void)FairExecuteDartFunctionAsync:(NSString *)data callback:(JSValue *)callback
{
    [[FairDartBridge sharedInstance] sendMessageToDart:data callback:^(id result, NSError *error) {//调用dart
        [[FairJSBridge sharedInstance] invokeJSFunction:callback param:result]; //dart回来成果result,回调js callback
    }];
}

通用js办法名界说

通用姓名的js办法界说,js办法名经过channel调用dart,dart履行成果callback 回传js

NSString * const FairExecuteDartFunctionAsync = @"jsInvokeFlutterChannel";
NSString * const FairExecuteDartFunctionSync = @"jsInvokeFlutterChannelSync";
// JS 异步调用 Dart
_context[FairExecuteDartFunctionAsync] = ^(id receiver, JSValue *callback) { //注册js 办法,通用的js办法名
    FairStrongObject(strongSelf, weakSelf)
    NSString *data = [strongSelf convertStringWithData:receiver];
    if ([strongSelf.delegate respondsToSelector:@selector(FairExecuteDartFunctionAsync:callback:)]) {
        [strongSelf.delegate FairExecuteDartFunctionAsync:data callback:callback];//js调用dart,成果回调js
    }
};
// JS 同步调用 Dart
_context[FairExecuteDartFunctionSync] = ^(id receiver, JSValue *callback) {
    FairStrongObject(strongSelf, weakSelf)
    NSString *data = [strongSelf convertStringWithData:receiver];
    if ([strongSelf.delegate respondsToSelector:@selector(FairExecuteDartFunctionSync: callback:)]) {
        [strongSelf.delegate FairExecuteDartFunctionSync:data callback:callback];
    }
};

JS端界说

fair_core.js

function setState(pageName, obj) {
    console.log('JS:setState()_before' + pageName + '-' + obj);
    let p = {};
    p['funcName'] = 'setState';
    p['pageName'] = pageName;
    // console.log('JS:setState(states)'+JSON.stringify(Object.getOwnPropertySymbols(obj)));
    obj();
    p['args'] = null;
    let map = JSON.stringify(p);
    console.log('JS:setState()' + map);
    invokeFlutterCommonChannel(map);
}
const invokeFlutterCommonChannel = (invokeData, callback) => {
    console.log("invokeData" + invokeData)
    jsInvokeFlutterChannel(invokeData, (resultStr) => {
        console.log('resultStr' + resultStr);
        if (callback) {
            callback(resultStr);
        }
    });
};

业务逻辑js文件

GLOBAL['#FairKey#'] = (function(__initProps__) {
    const __global__ = this;
    return runCallback(function(__mod__) {
        ///.....省掉
        setState('#FairKey#', function dummy() {});
        ///.....省掉
    }
})(convertObjectLiteralToSetOrMap(JSON.parse('#FairProps#'))); 

逻辑JS文件FairWidget加载

FairWidget烘托界面界说

    @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    _fairApp ??= FairApp.of(context);
    //加载js的文件地址
    _resolveFairRes(_fairApp!, FairJSFairJSDecoderHelper.transformPath(widget.path));
  }

加载一切JS逻辑文件

Future<dynamic> _resolveFairRes(FairApp _mFairApp, String? jsPath) async {
  final results = await Future.wait([
        _mFairApp.runtime.addScript(state2key, resolveJS, widget.data),
        _mFairApp.register(this)
      ]);
}

逻辑JS文件内容加载到内存,进行#FairKey##fairProps#形式字符串匹配替换,替换成实践的运行时的变量值

  @override
  Future<dynamic> addScript(String pageName, String scriptSource, dynamic props) async {
    // var scriptSource = await rootBundle.loadString(script);
    var fairProps;
    if (props != null && props['fairProps'] != null) {
      fairProps = props['fairProps'];
    } else {
      fairProps = '{}';
    }
    if (fairProps is String) {
      fairProps = fairProps.replaceAll('\\', '\\\\');
    }
    scriptSource = scriptSource.replaceFirst(RegExp(r'#FairProps#'), fairProps);
    scriptSource = scriptSource.replaceAll(RegExp(r'#FairKey#'), pageName);
    var map = <dynamic, dynamic>{};
    map[FairMessage.PATH] = scriptSource;
    map[FairMessage.PAGE_NAME] = pageName;
    return _channel!.loadJS(jsonEncode(map), null);
  }

dart端完成

BasicMessageChannel通道注册handler回调,监听native事情调用

final String COMMON_MESSAGE_CHANNEL = 'com.wuba.fair/common_message_channel';
_commonChannel ??=
    BasicMessageChannel<String?>(COMMON_MESSAGE_CHANNEL, StringCodec());
_commonChannel!.setMessageHandler((String? message) async { //监听native音讯
  print('来自native端的音讯:$message');
  //js 异步调用dart中的相关办法
  var data = json.decode(message??'');
  var funcName = data['funcName']?.toString();
  if (funcName == 'invokePlugin') {
    var p = await FairPluginDispatcher.dispatch(message);
    return p;
  }
  _callback?.call(message); //履行native音讯,一般便是js调用dart,由js宣布的 
  return 'reply from dart';
});

callback办法绑定,即经过channel监听到事情后的分发处理

void setMessageHandler(StringMsgCallback callback) {
  _callback = callback; //_callback
}
Runtime._internal() {
    init(true);
    _channel ??= FairMessageChannel();
    //接纳setState()的信息
    _channel!.setMessageHandler((message) { //_callback  ①这个callback其实不会调用的
      var data = json.decode(message ?? '');
      var className = data['pageName'];
      var call = _callBacks[className];
      call?.call(message); //
      return null;
    });
}

另外一种办法callback的绑定

void bindCallback(String key, RuntimeCallback callback) { //_callback
_callBacks[key] = callback;
}

经过FairHandler目标对channel事情音讯进行处理

FairHandler(this._runtime) {
    //接纳native发送过来的音讯,实践上是js发送的音讯,经过native端透传过来
    _runtime.getChannel().setMessageHandler((String? message) {   //callback ②会调用这个callback
      var data = json.decode(message ?? '');
      var funcName = data['funcName']?.toString();
      var pageName = data['pageName'];
      var args = data['args']??{};
      if (funcName == null || funcName.isEmpty) {
        return '';
      }
      //当用户调用setState的时分相当于改写了数据,告诉改写页更新
      if (funcName == 'setState') {
        _dispatchMessage(pageName, jsonEncode(args));
        return '';
      }
      // //js 异步调用dart中的相关办法
      // if (funcName == 'invokePlugin') {
      //   FairPluginDispatcher.dispatch(jsonEncode(args))
      //       .then((value) => _runtime.getChannel().sendCommonMessage(value));
      //   return '';
      // }
      return '';
    });
}

AppState

每一个fairWidget的FairState状况都在大局AppState中进行管理

mixin AppState {
  final modules = FairModuleRegistry();
  final bindData = <String, BindingData>{};
  final _proxy = ProxyMirror();
  final runtime = Runtime(); //这儿一个runtime
  final _mFairHandler = FairHandler(Runtime()); //这儿有一个runtime 这是两个不同的runtime目标 
}
class FairApp extends InheritedWidget with AppState 
Future<dynamic> register(FairState state) async {//每一个FairWidget都会调用
    log('register state: ${state.state2key}');
    _mFairHandler.register(state); //_mFairHandler 这儿用。内部一个runtime目标逻辑家
    var delegate = state.delegate;
    delegate.setRunTime(runtime); //这儿运用的runtime目标
    // await delegate.bindAll({});
    bindData.putIfAbsent(
      state.state2key,
      () => BindingData(
        modules,
        functions: delegate.bindFunction(),
        values: delegate.bindValue(),
      ),
    );
    return Future.value(null);
}

runtime单例目标

经过界说单例目标,channel通道交互都在同一处履行

final runtime = Runtime(); //这儿一个runtime
delegate.setRunTime(runtime); //这儿运用的runtime目标
final _mFairHandler = FairHandler(Runtime()); //这儿也创立一个runtime
FairHandler(this._runtime) {
    //接纳native发送过来的音讯,实践上是js发送的音讯,经过native端透传过来
    _runtime.getChannel().setMessageHandler((String? message) {
    }
}
class Runtime implements IRuntime {
  static final Runtime _runtime = Runtime._internal();
  factory Runtime() {//结构办法 创立出来的是一个静态大局变量。所以这个runtime目标是一个单例目标
    return _runtime;
  }
  Runtime._internal() {
    init(true);
    _channel ??= FairMessageChannel();
  }
}

FairWidget state setState调用

js如何调用dart setState改写界面?

每一个FairWidget对应的State都有一个stateKey做为键值在大局表中存储

因为runtime dart通道是一个大局目标,这儿面一切的js调用dart端的办法都将在上述所描绘的setMessageHandler音讯处理中分发,那一个页面中一起多个Fairwidget如何找到自己对应的Flutter State目标呢,这便是经过map存储:

咱们先了解到:每一个FairWidget都有一个自己仅有标识 state2key,这个state2key 是由pageName和静态ID自增拼接,防止同一个FairWidget多次运用重复问题。

class FairState extends State<FairWidget> with Loader, AutomaticKeepAliveClientMixin<FairWidget> implements FairMessageCallback<String> {
late String state2key;
  @override
void initState() {
  super.initState();
  state2key = GlobalState.id(widget.name);
}
static String id(String? prefix) {
  return '$prefix#${GlobalState._counter++}';
}
String getMessageKey() => state2key;
}

_mFairHandler.register(state);

界说一个map目标pageHistories 存储每一个页面的

class FairHandler { 
  final pageHistories = <String, FairMessageCallback<String>>{};
  final Runtime _runtime;
  String _dispatchMessage(String pageName, String message) {
    pageHistories[pageName]?.call(message);
    return 'Reply from Dart';
  }
  void register(FairMessageCallback<String> state) {
    log('register state: ${state.getMessageKey}');
    pageHistories[state.getMessageKey()] = state;
  }
  void unregister(FairMessageCallback<String> state) {
    var key = state.getMessageKey();
    log('unregister state: $key');
    pageHistories.remove(key);
  }
}

FairHandler是一个app等级的目标:

mixin AppState {
  final _mFairHandler = FairHandler(Runtime());
  Future<dynamic> register(FairState state) async {
    _mFairHandler.register(state);
  }
}

FairState 完成 FairMessageCallback协议

FairState持有 FairDelegate delegate目标,这个delegate 是Fair运行时一切相关运行时操作的一个封装,其间一个便是调用setState办法。

经过上面的FairHandler的pageHistories这个map表,经过stateKey找到对应state,由state的delegate目标,调用state_state?.setState(fn);办法。

FairMessageCallback 界说:

abstract class FairMessageCallback<T> {
  void call(T t);
  String getMessageKey();
}

FairState 完成 FairMessageCallback协议:

class FairState extends State<FairWidget> with Loader, AutomaticKeepAliveClientMixin<FairWidget> implements FairMessageCallback<String> {
  @override
  void call(String t) {
    var params={};
    try {
      params= jsonDecode(t);
    } catch (e) {
      print(e);
    }
    delegate.notifyValue(params); //
  }
  @override
  String getMessageKey() => state2key;
  void initState() {
    super.initState();
    state2key = GlobalState.id(widget.name);
    delegate = widget.delegate ?? GlobalState.of(widget.name).call(context, widget.data); //获取delegate目标从FairWidget传的或是是FairApp目标中创立的从中获取大局delegate
    delegate._bindState(this);//保存当时 Widget state目标d
    delegate.initState();  //调用delegate的initState办法 用户可以在FairDelegatec重写一些自界说操作
  }
}

FairDelegate 界说:

class FairDelegate extends RuntimeFairDelegate {
  FairState? _state;
 late String _key;
  void _bindState(FairState? state) {
    assert(state != null, 'FairState should not be null');
    _state = state!;
    _key = state.state2key;
  }
  @override
  void setState(VoidCallback fn) {
    if (_state == null || !_state!.mounted) return;
    // ignore: invalid_use_of_protected_member
    _state?.setState(fn); //这儿调用state目标的setState的改写界面
    _state?._reload();
  }
  //获取js端的数据,改写指定数据
  void notifyValue(Map values) {
    // values.forEach((key, value) {
    //   _valueMap[key]?.value = value;
    // });
    setState(() {});
  }
}

总结

归纳上面代码分析,咱们就知道了FairWidget烘托完成后,页面中的逻辑部分转换成了js被加载到内存中,当履行js逻辑功用时,经过native端注册的js通用办法姓名的_context[FairExecuteDartFunctionAsync]办法,经过native端FlutterBasicMessageChannel类型的flutterBasicMessageChannel和dart端类型为BasicMessageChannel_commonChannel调用dart,dart经过音讯监听进行分发,每一个FairWidget对应一个仅有的statekey,每一个state存储到一个FairApp的大局map目标中,当履行setState办法时,js端传入pageName,从大局map中取出state调用其setState办法。这样的一个过程就完成了调用dart端履行setState界面改写的全部流程。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。