微猫Android SDK分析
2015年10月28日 15:41无意中知道微猫 这个网站, 他们是这样介绍自己的
我们,致力于社会化电子商务解决方案的实践。
我们的创始团队成员,曾在多家国内知名互联网公司和跨国企业担任高管。
那就关怀一下, 下载了他们的Android SDK 看看. 觉得他们处理网页和原生交互的方式设计还是比较不错的.
先看一下SDK的调用方式:
webView = (WemartJSBridgeWebView) findViewById(R.id.webView);
String ua = webView.getSettings().getUserAgentString();
webView.getSettings().setUserAgentString(ua + "; WemartApp/1.0; app=XXX");
webView.initContext("http://www.wemart.cn/v2/sdk/WemartJSBridge.js");
webView.setWebChromeClient(new WebChromeClient());
webView.loadUrl("http://..."); //店铺链接
webView.registerEvent("nativePay", new WemartJSBridgeHandler() {
@Override
public void handler(String data, final WemartJSBridgeCallBack callback) {
pay(data, callback);
}
});
调用方式很简单, 就一个WemartJSBridgeWebView
统管全部交互. 这个类主要干的事情是接管了页面状态处理并维持一个回调集合.
WemartJSBridgeWebView
里面的BridgeWebViewClient
内部类, 主要是重写了WebViewClient
类的这两个方法
- public void onPageFinished(WebView view, String url)
- public boolean shouldOverrideUrlLoading(WebView view, String url)
我们就这两个方法展开分析.
onPageFinished
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (this.isCurrentlyLoading || url.startsWith("about:")) {
this.isCurrentlyLoading = false;
if (WemartJSBridgeWebView.this.toLoadJs != null) {
JSBridgeUtil.webViewLoadJs(view, WemartJSBridgeWebView.this.toLoadJs);
}
if (WemartJSBridgeWebView.this.startupMessage != null) {
for (JSBridgeMessage m: WemartJSBridgeWebView.this.startupMessage) {
WemartJSBridgeWebView.this.dispatchMessage(m);
}
WemartJSBridgeWebView.this.startupMessage = null;
}
}
}
在onPageFinished里面控制了在加载正常页面时只执行一次, 因为onPageFinished有可能被多次执行(这是一个坑).
这个方法主要是做了两件事:
让webview加载之前**webView.initContext(url)**设置js文件 . 这个js文件的作用就是用来和客户端进行交互, 有兴趣可以阅读一下.
将页面加载完成之前的JsBridge的消息队列拿出来全部消耗掉(同步执行js语句), 并在最后将队列置为null.
shouldOverrideUrlLoading
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
try {
url = URLDecoder.decode(url, "UTF-8");
} catch(UnsupportedEncodingException e) {
e.printStackTrace();
}
Logger.i("WemartJSBridge", "\u8c03\u7528 shouldOverrideUrlLoading, url = " + url);
if (url.startsWith("wtjs://return/")) {
WemartJSBridgeWebView.this.handlerReturnData(url);
return true;
} else if (!url.startsWith("wtjs://")) {
return super.shouldOverrideUrlLoading(view, url);
} else {
WemartJSBridgeWebView.this.flushMessageQueue();
return true;
}
}
在shouldOverrideUrlLoading里面分别处理了以wtjs://
开头的后面跟的return
和非return
这两种scheme.
return
表示返回数据, 然后调起相应的回调事件进行响应;非return
表示请求事件(一般来自于原生需要发起), 会注册一个回调事情然后在return
时被响应掉.非return
scheme可以在dispatchMessage(JSBridgeMessage )
执行后被主动调起, 所以可以用于原生向网页端请求数据.
……(大概逻辑是这样, 里面的交互细节就不讲了)
总结
整体实现JsBridge的方式很不错, 功能完备. 但其内部实现过于复杂, 扩展性很差, 性能开销有待优化.
文章作者: qbeenslee