微猫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时被响应掉. 非returnscheme可以在dispatchMessage(JSBridgeMessage )执行后被主动调起, 所以可以用于原生向网页端请求数据.

……(大概逻辑是这样, 里面的交互细节就不讲了)

总结

整体实现JsBridge的方式很不错, 功能完备. 但其内部实现过于复杂, 扩展性很差, 性能开销有待优化.

文章作者: qbeenslee

CC BY-NC 4.0