jockeyjs库对h5和native代码交互做了优美的封装。
你可以写出像下面这种风格的代码,本文对它的实现做一个分析。
//Listen for an event from Javascript and log a message when we have receied it. jockey.on("event-name", new JockeyHandler() { @Override protected void doPerform(Map<Object, Object> payload) { Log.d("jockey", "Things are happening"); } });
项目地址:https://github.com/tcoulter/jockeyjs
jockey的实现类是JockeyImpl.java
@Override
public void on(String type, String data, JockeyHandler... handler) {
if (!this.handles(type)) {
CompositeJockeyHandler compositeJockeyHandler = new CompositeJockeyHandler();
compositeJockeyHandler.setData(data);
_listeners.put(type, compositeJockeyHandler);
}
_listeners.get(type).add(handler); //从这里可以看到jockey对event进行了批处理
}
因此我们搜索_listeners,ctrl f搜索下这个变量在类中的用处,跟踪到下面这个函数。
protected void triggerEventFromWebView(final WebView webView,
JockeyWebViewPayload envelope) {
final int messageId = envelope.id;
String type = envelope.type;
if (this.handles(type)) {
final JockeyHandler handler = _listeners.get(type); //取到handler
handler.perform(envelope.payload, new OnCompletedListener() {
@Override
public void onCompleted() {
// This has to be done with a handler because a webview load
// must be triggered
// in the UI thread
_handler.post(new Runnable() {
@Override
public void run() {
triggerCallbackOnWebView(webView, messageId, handler.getData());
}
});
}
});
}
}
可以想象到程序必定在某个地方(某个类)监听到我们想要的event,然后triggerEventFromWebView。
启动工程中ctrl f搜索大法搜索 triggerEventFromWebView。
因此我们找到了这个类-->JockeyWebViewClient.java
public void processUri(WebView view, URI uri)
throws HostValidationException {
String[] parts = uri.getPath().replaceAll("^\\/", "").split("/");
String host = uri.getHost();
JockeyWebViewPayload payload = checkPayload(_gson.fromJson(
uri.getQuery(), JockeyWebViewPayload.class));
if (parts.length > 0) {
if (host.equals("event")) {
getImplementation().triggerEventFromWebView(view, payload);
} else if (host.equals("callback")) {
getImplementation().triggerCallbackForMessage(
Integer.parseInt(parts[0]));
}
}
}
然后再搜索processUri,我们看到
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (delegate() != null
&& delegate().shouldOverrideUrlLoading(view, url))
return true;
try {
URI uri = new URI(url);
if (isJockeyScheme(uri)) { //因此jockey封装event的方式很简单,就是再js那边加一个jocky的头部 如果是jocky的头部
//就捕捉相应的事件进行处理
processUri(view, uri);
return true;
}
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (HostValidationException e) {
e.printStackTrace();
Log.e("Jockey", "The source of the event could not be validated!");
}
return false;
}
总结一下,jocky对于监听webview的事件的实现其实很简单,就是在shouldOverrideUrlLoading的地方增加一个jocky头部。