第22章 WebView与Hybrid开发
说到Hybrid开发,我脑子里第一个蹦出来的画面就是——几年前那个深夜,我盯着手机上白屏的WebView页面,咖啡凉了都没察觉。那时候我刚接手一个电商App,首页用WebView加载H5活动页,结果用户反馈「打开慢得像蜗牛」。嗯,从那以后,我对WebView的每一个配置项都格外敏感。
这一章,咱们就来聊聊WebView那些事儿。说白了,它就是Android里一个能加载网页的控件,但用好它,远比你想象的要复杂。
本章核心脉络:基础配置 → JS与Java互调 → 缓存策略 → 加载优化 → 框架选型
22.1 WebView基础配置
先说说最基础的东西。每次创建WebView,我都会先做一套「标准配置」。你想想看,如果不配置,默认的WebView连JavaScript都不开,那跟看一张图片有什么区别?
// 我个人习惯封装一个配置方法
WebView webView = findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
// 启用JavaScript——这是Hybrid的基础
settings.setJavaScriptEnabled(true);
// 开启DOM存储,H5页面经常用到
settings.setDomStorageEnabled(true);
// 设置缓存模式
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
// 允许混合内容(HTTP+HTTPS)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
webView.getSettings().setMixedContentMode(
WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
// 缩放相关
settings.setSupportZoom(true);
settings.setBuiltInZoomControls(false); // 不显示缩放按钮
settings.setDisplayZoomControls(false);
小提示:setJavaScriptEnabled(true) 一定要在加载URL之前调用。我曾经见过有人写反了顺序,结果页面上的交互全部失效,排查了半天才发现是这个问题。
还有一点要注意——WebView的User-Agent。有些H5页面会根据UA做适配,我习惯在初始化时追加一个自定义标识:
String ua = settings.getUserAgentString();
settings.setUserAgentString(ua + " /MyApp/1.0");
22.2 JS与Java互调(JsBridge)
这是Hybrid开发的核心。说白了,就是让Java代码能调用JS方法,JS也能调用Java代码。双向通信,缺一不可。
22.2.1 Java调用JS
这个比较简单。Android 4.4之后推荐用 evaluateJavascript,它比 loadUrl 更高效,还能拿到返回值。
// 调用JS方法,不关心返回值
webView.loadUrl("javascript:showToast('Hello from Java')");
// 推荐方式:可以获取返回值
webView.evaluateJavascript(
"javascript:getUserInfo()",
new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
// value就是JS返回的JSON字符串
Log.d("WebView", "JS返回: " + value);
}
}
);
22.2.2 JS调用Java
这里有个坑,我踩过。先看代码:
// 定义一个接口类
public class JsInterface {
@JavascriptInterface
public void share(String title, String url) {
// 调用原生分享功能
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, title + " " + url);
intent.setType("text/plain");
context.startActivity(Intent.createChooser(intent, "分享"));
}
}
// 注册到WebView
webView.addJavascriptInterface(new JsInterface(), "Android");
然后在H5页面里这样调用:
window.Android.share("标题", "https://example.com");
⚠️ 重要提醒:@JavascriptInterface 注解在Android 4.2以上是必须的,否则JS无法调用。我曾经在旧项目里忘了加这个注解,结果线上反馈说分享按钮点了没反应,排查了好久才发现是兼容性问题。
22.2.3 JsBridge框架
如果项目里JS和Java交互频繁,我建议直接用JsBridge框架。它封装了协议解析、回调管理等逻辑,比自己手写要稳定得多。
// 使用JsBridge框架的示例
webView.registerHandler("submitOrder", new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {
// data是JS传过来的JSON字符串
// 处理订单逻辑...
// 回调给JS
function.onCallBack("{\"code\":200, \"msg\":\"success\"}");
}
});
22.3 WebView缓存策略
缓存这东西,用好了是神器,用不好就是噩梦。我见过一个项目,因为缓存策略配置不当,用户看到的永远是旧页面,气得直骂娘。
WebView提供了几种缓存模式:
| 模式 | 说明 | 适用场景 |
|---|---|---|
| LOAD_DEFAULT | 默认模式,根据cache-control决定 | 大多数情况 |
| LOAD_CACHE_ELSE_NETWORK | 有缓存就用缓存,没有才联网 | 离线阅读、新闻类App |
| LOAD_NO_CACHE | 不使用缓存,每次都从网络加载 | 实时性要求高的页面 |
| LOAD_CACHE_ONLY | 只使用缓存,不联网 | 离线模式 |
我个人习惯的做法是:
// 先尝试用缓存,如果缓存过期再联网
if (NetUtils.isConnected(context)) {
settings.setCacheMode(WebSettings.LOAD_DEFAULT);
} else {
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
}
避坑指南:我曾经遇到过一个诡异的问题——明明服务器更新了页面,但用户手机上显示的还是旧内容。后来发现是WebView的缓存数据库没有清理。建议在App版本升级时,主动清除WebView缓存:webView.clearCache(true);
22.4 H5页面加载优化
H5页面加载慢,是Hybrid开发最常见的痛点。我总结了几条实战经验:
- 预加载WebView:在App启动时提前初始化一个WebView实例,用户点击时直接复用。我做过测试,这样能减少200-300ms的初始化时间。
- 资源预加载:把H5常用的JS、CSS库提前下载到本地,WebView加载时拦截网络请求,直接返回本地文件。
- 启用硬件加速:在AndroidManifest中给WebView所在的Activity开启硬件加速。
// 在AndroidManifest中
<activity
android:name=".WebViewActivity"
android:hardwareAccelerated="true" />
- 减少重定向:H5页面每多一次重定向,加载时间就多几百毫秒。跟后端沟通,尽量一次到位。
- 使用WebView预渲染:Android 7.0以上支持WebView预渲染,可以在用户点击前就开始加载页面。
核心思路:能提前做的绝不等到用时再做,能本地化的绝不走网络。说白了,就是「空间换时间」。
22.5 Hybrid框架对比(Cordova / Flutter)
选框架这件事,我经历过不少纠结。咱们来对比一下主流的两个方案:
| 维度 | Cordova | Flutter |
|---|---|---|
| 渲染方式 | WebView渲染 | 自研引擎渲染 |
| 性能表现 | 中等,依赖WebView | 优秀,接近原生 |
| 开发语言 | HTML+JS+CSS | Dart |
| 插件生态 | 丰富,但质量参差不齐 | 官方维护,质量较高 |
| 学习成本 | 低,前端开发者即可上手 | 中等,需要学习Dart |
| 适合场景 | 快速原型、简单业务 | 复杂交互、高性能要求 |
说说我的个人看法。如果你团队里前端资源充足,项目又比较急,Cordova是个不错的选择。我早期做过一个企业内部工具App,用Cordova两周就搞定了,虽然性能一般,但够用。
但如果你要做的是面向C端用户的产品,对流畅度有要求,我建议直接上Flutter。虽然学习曲线陡一点,但用户体验的差距是肉眼可见的。我记得有一次给客户演示两个版本,客户直接说「这个Flutter版的明显更顺滑」。
⚠️ 注意:不要盲目追求新技术。如果团队里没人熟悉Dart,硬上Flutter可能会拖慢项目进度。技术选型,说白了就是「合适」两个字。
嗯,关于WebView和Hybrid开发,核心内容就是这些。从基础配置到JS互调,从缓存策略到加载优化,再到框架选型,每一步都有坑,也都有解法。希望这些经验能帮你少走一些弯路。
公众号:蓝海资料掘金营,微信deep3321