微猫Android SDK分析

无意中知道微猫这个网站, 他们是这样介绍自己的

我们,致力于社会化电子商务解决方案的实践。
我们的创始团队成员,曾在多家国内知名互联网公司和跨国企业担任高管。

其实这些和本文并没有什么关系, 只是仰望一下文青的世界.

这对于无知的我来说实在是太高大上了

那就关怀一下, 下载了他们的Android SDK看看. 觉得他们处理网页和原生交互的方式设计还是比较不错的.

先看一下SDK的调用方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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的方式很不错, 功能完备. 但其内部实现过于复杂, 扩展性很差, 性能开销有待优化.

本文为原创,转载请遵守本站版权声明

更新于:2017年2月5日 01:02