在移动开发领域,存在WebApp、独立App和混合应用等多种开发模式。这些模式各有其特色、优点和适用的场景,一直是开发者关注的焦点。它们在开发成本、跨平台能力、功能体验和沟通交互等方面有着不同的表现,这些方面都值得我们深入研究和探讨。
WebApp的特点
WebApp把页面放在服务器上,用户用浏览器就能访问,并不像独立的APP。它维护起来成本低,更新时无需通知用户,也不需要手动升级。像企业宣传页面或小型信息查询站点这样的简单应用,以网站形式存在,既节省了开发APP的精力,又避免了后续通知用户升级的麻烦。这种开发模式在节省人力和管理成本方面表现不错。但它的使用体验有限,不能像APP那样深度整合手机功能。
WebApp无法像APP那样直接安装,这一点非常直观。这就导致它在吸引用户方面遇到困难,不能像应用商店里的APP那样,用户可以轻松安装使用。用户必须记住网址,或者通过搜索引擎去寻找,这样的方法在便捷性上大大降低,对用户留存非常不利。
App的优缺点
安卓和iOS平台的App开发,大家都很熟悉,属于原生应用。不过,它的开发成本较高,这是大家普遍关心的问题。每个平台都需要独立开发,这导致覆盖更多用户群体时,所需的开发资源投入巨大。而且,它无法实现跨平台,这也是一个让人头疼的问题。若想实现跨平台,几乎需要重新开发。
原生APP在功能和性能上表现确实出色。以热门游戏APP和大型商业应用为例,它们充分运用了原生系统的特性,如调用摄像头、传感器等,实现了流畅的操作体验,从而提供了极致的用户体验。这也是原生APP吸引众多用户的关键所在。
混合应用的原理
混合应用成为我们今日关注的焦点,它仿佛是WebApp与App的融合产物。其核心在于,将APP中部分需要动态更新的内容通过H5技术实现,再借助原生网页加载控件来加载H5页面。这样的做法颇具优势。以开发电商APP为例,若商品展示部分采用H5技术,则无需更新整个APP,即可随时更新商品信息。
window.say = (name) => {
alert(name)
}
从开发的角度看,H5代码只需一次开发便能在安卓和iOS两个平台运行,这显著降低了开发成本。对于创业项目在初期,资金和开发时间往往受限,采用混合应用模式便成为理想之选。它不仅能让项目迅速上线,还能在两大主流手机操作系统上以较低的成本运行。
private void isAutoUser () {
String username = mSpHelper.getAutoUser();
if (TextUtils.isEmpty(username)) {
return;
}
// 1.Android: loadUrl (Android系统4.4- 支持)
// 该方法的弊端是无法获取函数返回值;
// say 方法是H5端挂载在window对象上的方法。
mWebView.loadUrl("javascript:say('" + username + "')")
// 2.Android: evaluateJavascript (Android系统4.4+ 支持)
// 这里着重介绍 evaluateJavascript,这也是目前主流使用的方法。
// 该方法可以在回调方法中获取函数返回值;
// say 方法是H5端挂载在window对象上的方法。
mWebView.evaluateJavascript("javascript:say('" + username + "')", new ValueCallback() {
@Override
public void onReceiveValue(String s) {
//此处为 js 返回的结果
}
});
// 下面这两种通信方式用的不多,这里就不着重介绍了。
// 3.Android: loadUrl (Android系统4.4- 支持)
// 直接打开某网页链接并传递参数,这种也能给H5端传递参数
// mWebView.loadUrl("file:///android_asset/shop.html?name=" + username);
// 4. Android端还可以通过重写onJsAlert, onJsConfirm, onJsPrompt方法拦截js中调用警告框,输入框,和确认框。
}
开发混合应用的成本并不高,这一点对于众多小型开发团队或是初创企业来说,无疑是一个极具吸引力的优势。以一个简单的社交APP为例,若选择混合应用开发模式,不仅能在初期节省资金投入,而且后续的功能扩展也会变得更为便捷。此外,混合应用还能实现跨平台运行,从而吸引到更多的潜在用户。
维护混合应用的成本并不高,而且其功能可以实现重复利用。以APP内不同页面为例,若功能类似或存在共同逻辑,便能够实现代码的复用。此外,在性能与用户体验方面,混合应用通常优于WebApp。以在线教育APP为例,混合应用能够实现流畅的视频播放,稳定性远超单纯的WebApp。
// Objective-C
// say 方法是H5端挂载在window对象上的方法
[self.webView evaluateJavaScript:@"say('params')" completionHandler:nil];
// Swift
// say 方法是H5端挂载在window对象上的方法
webview.stringByEvaluatingJavaScriptFromString("say('params')")
通信原理之App端调用H5端
// 这里的对象名 androidJSBridge 是可以随意更改的,不固定。
addJavascriptInterface(new MyJaveScriptInterface(mContext), "androidJSBridge");
// MyJaveScriptInterface类里面的方法
@JavascriptInterface
public aliPay (String payJson) {
aliPayHelper.pay(payJson);
// Android 在暴露给 H5端调用的方法能直接有返回值。
return 'success';
}
在混合应用里,通信扮演着核心角色。当App端需要调用H5端的方法,必须使用绑定在对象上的方法。安卓和IOS系统各自有独特的挂载方法,这要求开发者必须遵循各自的操作规范。比如,安卓的挂载方式与IOS的不一样,一旦操作不当,可能会造成通信失败。
在IOS系统中,提供给web端调用的接口不能直接返回数据。若需要返回数据,开发者必须通过调用web端的其他方法来实现值的传递。这一点是设计通信逻辑时不可忽视的细节。忽视它,可能会引发数据交互的故障,从而对APP的整体功能造成不良影响。
// 这里的 androidJSBridge 是根据上面注册的名字来的。
// js调用Android Native原生方法传递的参数必须是基本类型的数据,不能是引用数据类型,如果想传递引用类型需要使用JSON.stringify()。
const result = window.androidJSBridge.aliPay('string参数');
console.log(result);
在使用H5端调用安卓端方法时,需按照安卓.方法名(参数)的格式进行,且方法名称可自行设定。然而,调用IOS端方法时,则必须遵循iOS.方法名.(参数)的固定格式,这一点开发者务必铭记。至于参数传递,H5端调用安卓端方法时,只能传递基本数据类型的参数;若需传递引用数据类型,则必须借助JSON.()进行处理。相较之下,IOS端在参数传递方面更为灵活,既可传递基本数据类型,亦能传递引用数据类型。
#pragma mark - OC注册供JS调用的方法 register方法
- (void)addScriptFunction {
self.wkUserContentController = [self.webView configuration].userContentController;
[self.wkUserContentController addScriptMessageHandler:self name:@"register"];
}
#pragma mark - register方法
- (void)register:(id)body {
NSDictionary *dict = body;
[self.userDefaults setObject:[dict objectForKey:@"password"] forKey:[dict objectForKey:@"username"]];
不能直接返回结果,需要再次调用H5端的方法,告诉H5端注册成功。
[self.webView evaluateJavaScript:@"registerCallback(true)" completionHandler:nil];
}
另外,H5端可以调用安卓端方法并直接获得返回值,然而,IOS端则不行。举例来说,在金融类混合应用中,若需在H5页面获取用户在原生APP中的账户信息等数据,就必须依照这些通信规则,以确保数据的准确获取。
在实际开发过程中,我们是否思考过,遇到特殊状况时,这些通信规则能否有所调整?欢迎各位在评论区留言讨论。另外,若您觉得这篇文章对您有所帮助,不妨点赞或分享,让更多人受益。
// 与android不同,ios这里的webkit.messageHandlers是固定写法,不能变。
// 不传参数
window.webkit.messageHandlers.register.postMessage(null);
// 传递参数
// 与android不同,ios这里的参数可以是基本类型和引用数据类型。
window.webkit.messageHandlers.register.postMessage(params);