2024年JSBridge原理解析——以WebviewJavascriptBridge实现方式为例,kotlin面试题

总结

根据路线图上的重点去进行有针对性的学习,在学习过程中,学会写笔记,做总结。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

这里分享一些前端学习笔记:

  • html5 / css3 学习笔记

  • JavaScript 学习笔记

  • Vue 学习笔记

window.WebViewJavascriptBridge = {

registerHandler: registerHandler,

callHandler: callHandler,

disableJavscriptAlertBoxSafetyTimeout: disableJavscriptAlertBoxSafetyTimeout,

_fetchQueue: _fetchQueue,

_handleMessageFromObjC: _handleMessageFromObjC

};

var sendMessageQueue = [];

var messageHandlers = {};

var responseCallbacks = {};

var uniqueId = 1;

(4)继续判断,如果是 isQueueMessageURL,那么这就是个处理消息的回调,需要执行一些消息处理的方法(第四步会详细讲)

2-4、webview 调用 native 能力

当 native 和 webview 都注册好了 Bridge 之后,双方就可以互相调用了,这里先介绍 webview 调用 native 能力的过程。

2-4-1、webview 侧 callHandler

当 webview 调用 native 时,会调用 callHandler 方法,这个方法具体逻辑如下:

bridge.callHandler(‘ObjC Echo’, {‘key’:‘value’}, function responseCallback(responseData) {

console.log(“JS received response:”, responseData)

})

function callHandler(handlerName, data, responseCallback) {

if (arguments.length == 2 && typeof data == ‘function’) {

responseCallback = data;

data = null;

}

_doSend({ handlerName:handlerName, data:data }, responseCallback);

}

function _doSend(message, responseCallback) {

if (responseCallback) {

var callbackId = ‘cb_’+(uniqueId++)+‘_’+new Date().getTime();

responseCallbacks[callbackId] = responseCallback;

message[‘callbackId’] = callbackId;

}

sendMessageQueue.push(message);

messagingIframe.src = CUSTOM_PROTOCOL_SCHEME + ‘😕/’ + QUEUE_HAS_MESSAGE;

}

实际上就是先生成一个 message,然后 push 到 sendMessageQueue 里,然后更改 iframe 的 src。

2-4-2、native 侧 flushMessageQueue

然后,当 native 端检测到 iframe src 的变化时,会走到 isQueueMessageURL 的判断逻辑,然后执行 WKFlushMessageQueue 函数,获取到 JS 侧的 sendMessageQueue 中的所有 message。

- (void)WKFlushMessageQueue {

[_webView evaluateJavaScript:[_base webViewJavascriptFetchQueyCommand] completionHandler:^(NSString* result, NSError* error) {

if (error != nil) {

NSLog(@“WebViewJavascriptBridge: WARNING: Error when trying to fetch data from WKWebView: %@”, error);

}

[_base flushMessageQueue:result];

}];

}

- (void)flushMessageQueue:(NSString *)messageQueueString{

if (messageQueueString == nil || messageQueueString.length == 0) {

NSLog(@“WebViewJavascriptBridge: WARNING: ObjC got nil while fetching the message queue JSON from webview. This can happen if the WebViewJavascriptBridge JS is not currently present in the webview, e.g if the webview just loaded a new page.”);

return;

}

id messages = [self _deserializeMessageJSON:messageQueueString];

for (WVJBMessage* message in messages) {

if (![message isKindOfClass:[WVJBMessage class]]) {

NSLog(@“WebViewJavascriptBridge: WARNING: Invalid %@ received: %@”, [message class], message);

continue;

}

[self _log:@“RCVD” json:message];

NSString* responseId = message[@“responseId”];

if (responseId) {

WVJBResponseCallback responseCallback = _responseCallbacks[responseId];

responseCallback(message[@“responseData”]);

[self.responseCallbacks removeObjectForKey:responseId];

} else {

WVJBResponseCallback responseCallback = NULL;

NSString* callbackId = message[@“callbackId”];

if (callbackId) {

responseCallback = ^(id responseData) {

if (responseData == nil) {

responseData = [NSNull null];

}

WVJBMessage* msg = @{ @“responseId”:callbackId, @“responseData”:responseData };

[self _queueMessage:msg];

};

} else {

responseCallback = ^(id ignoreResponseData) {

// Do nothing

};

}

WVJBHandler handler = self.messageHandlers[message[@“handlerName”]];

if (!handler) {

NSLog(@“WVJBNoHandlerException, No handler for message from JS: %@”, message);

continue;

}

handler(message[@“data”], responseCallback);

}

}

}

当一个 message 结构存在 responseId 的时候说明这个 message 是执行 bridge 后传回的。取不到 responseId 说明是第一次调用 bridge 传过来的,这个时候会生成一个返回给调用方的 message,其 reponseId 是传过来的 message 的 callbackId,当 native 执行 responseCallback 时,会触发_dispatchMessage 方法执行 webview 环境的的 js 逻辑,将生成的包含 responseId 的 message 返回给 webview。

2-4-3、webview 侧 handleMessageFromObjC

function _handleMessageFromObjC(messageJSON) {

_dispatchMessageFromObjC(messageJSON);

}

function _dispatchMessageFromObjC(messageJSON) {

if (dispatchMessagesWithTimeoutSafety) {

setTimeout(_doDispatchMessageFromObjC);

} else {

_doDispatchMessageFromObjC();

}

function _doDispatchMessageFromObjC() {

var message = JSON.parse(messageJSON);

var messageHandler;

var responseCallback;

if (message.responseId) {

responseCallback = responseCallbacks[message.responseId];

if (!responseCallback) {

return;

}

responseCallback(message.responseData);

delete responseCallbacks[message.responseId];

} else {

if (message.callbackId) {

var callbackResponseId = message.callbackId;

responseCallback = function(responseData) {

_doSend({ handlerName:message.handlerName, responseId:callbackResponseId, responseData:responseData });

};

}

var handler = messageHandlers[message.handlerName];

if (!handler) {

console.log(“WebViewJavascriptBridge: WARNING: no handler for message from ObjC:”, message);

} else {

handler(message.data, responseCallback);

}

}

}

}

最后

推荐一些系统学习的途径和方法。

路线图

每个Web开发人员必备,很权威很齐全的Web开发文档。作为学习辞典使用,可以查询到每个概念、方法、属性的详细解释,注意使用英文关键字搜索。里面的一些 HTML,CSS,HTTP 技术教程也相当不错。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

HTML 和 CSS:

html5知识

css基础知识

  • 16
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值