马壮+陈年飞+史梦安+王志勃
摘要摘要:Hybrid混合開发模式利用Android/IOS Native UIWebView作为底层,采用本地编码与远程服务器进行通信,采用HTML、CSS、JavaScript等富客户端技术对显示层进行处理。该模式具有较为优秀的跨平台性、快速的软件更新、媲美Native代码的运行效率,在降低开发成本的同时保证了较好的用户体验,兼具Native APP和Web APP的优点。设计基于Android混合开发模式的软件架构,同时利用Android线程间通信技术以及工厂设计模式对架构进行优化改进,提高移动应用程序的开发效率。
关键词关键词:Android;WebView;Hybrid混合开发;设计模式;软件架构设计
DOIDOI:10.11907/rjdk.162691
中图分类号:TP319文献标识码:A文章编号文章编号:16727800(2017)001009304
引言
随着移动互联的兴起及移动设备计算能力的提升,各种移动应用程序层出不穷,快速的业务扩展要求必须提升开发效率。Android和IOS 原生开发的成本和效率很难取得实质性突破,且Native APP可移植性较差,不同平台需各自维护UI以保证用户体验的一致性。Web APP虽拥有超强的跨平台性,但受网络限制无法调用系统级API等问题一直没有较好的解决方案。因此,Hybrid混合APP应运而生[1]。
不同于Native APP针对特定平台的开发,Hybrid APP 表面上是一个Native APP,实际上显示的是存储在本地的Web App。Hybrid APP底层依赖于Native提供2.4ICE客户端开发
在实现服务器程序框架的基础上,即可实现多种功能的服务器程序。而客户端不需要考虑服务器端程序的编程语言及运行平台,只需通过调用Servant,即可与服务器进行数据通信,并使用服务器上提供的服务。
ICE客户端在建立连接时是通过继承 Ice::Application 类并重载 virtual int run(int, char*[])方法完成的,然后通过间接代理来调用服务器端相关操作。客户端代码流程为:使用Servant名称和适配器地址建立代理,代理转换为继承类的Servant的过程,操作完毕,释放相关资源。3结语
ICE中间件技术简单、高效,因此自诞生以来发展迅速。相对于国外已经出现较多关于ICE的学术探讨和应用研究,国内对ICE的研究及其在各个领域的应用都还处于起步阶段。本文采用ICE中间件技术设计应用系统通信框架,探讨体系结构并搭建框架,为基于ICE中间件的网络应用系统开发提供参考。利用此架构单独开发应用系统的通信框架,以后ICE版本的升级或通信代码的改变对整个应用系统的影响都比较小。服务器和客户端无需考虑通信带来的复杂性,可以专注于具体业务的实现。
Hybrid开发模式作为一种跨语言开发模式,开发应围绕通讯层展开。在Android平台中,WebView组件为Android提供了无需依赖浏览器即可加载Web页面的功能[3],并提供JS、Java相互通讯的接口。WebView使用addJavaScriptInterfaceAPI在HTML中注入本地Java对象,使得JS脚本可调用本地Java对象,Java使用loadUrlAPI加载本地页面资源或执行JS脚本[4]。
系统启动时,在主线程(UI线程)的onCreate中初始化WebView组件;通过loadUrlAPI加载本地HTML资源绘制界面,并使用addJavaScriptIntfaceAPI为当前HTML的JS脚本注入本地Java对象;WebView在解析JS脚本时会过滤该关键字作为对象进行处理;当脚本执行到注入的Java对象时,WebView会自动调用该Java对象相应的方法。逻辑处理完成后,使用 loadUrlAPI加载HTML资源或执行JS脚本。
但难以直接使用Hybrid技术开发。JS与Java之间的交互零散分布在整个系统中,资源分散不成体系;功能界限模糊,可扩展性差;系统耦合度高,开发效率低[5]。对此,可以设计一套基于Android的混合开发模式的软件架构。
2基于Hybrid开发模式的软件架构设计
2.1WebView扩展
为简化调用,提高方法灵活性,对WebView进行扩展。定义SWebView继承WebView,定义loadAssets()方法包装LoadUrl()以加载本地HTML资源,参数为html文件名。定义execJS()方法包装LoadUrl()以执行JS脚本,参数为JS函数名和JS参数。定义addJSInterface()方法包装addJavaScriptInterface()以加载本地Java对象,参数为对象和注入的对象名。SWebView类如图3所示。
为整合JS、Java零散交互资源,提高系统可扩展性、降低耦合,可将显示层抽象为“窗口”对象(BaseFrame)。加载HTML页面的两个参数:本地资源路径和注入的Java对象名不足以更新视图,比如执行JS脚本和页面返回逻辑。只能直接调用WebView的方法更新视图或关闭线程,提升模块耦合度。在处理页面返回逻辑时,系统中可以打开很多个页面,有返回上一页和退出程序两种情况,只有一个WebView容器。由于WebView的生命周期限制,需在BaseFrame中记录当前BaseFrame以支持goBack()处理。
由于WebView自始至终只有一个且运行在主线程中,页面切换所变更的只是HTML资源和注入的本地Java对象。可以结合装饰设计模式[6],在BaseFrame中包裹SWebView对象、Context上下文环境和自身实例,使BaseFrame可以最大限度的复用共有资源(如图4)。
BaseFrame定义3个带参构造方法,以灵活装载“窗口”对象资源。在BaseFrame中封装方法,调用自身SWebView的方法,使“窗口”视图更新操作都由BaseFrame自身执行,有效降低耦合。定义setVisible()调用SWebView的loadUrl()和addJSInterface(),在加载HTML资源的同时注入Java本地对象并记录当前BaseFrame。定义execJS()转发调用SWebView的execJS()。具体类图如图5所示。
3架构使用
系统启动时,在MainActivity的onCreate()方法中初始化WebView相关设置,并使用4个参数的构造方法(Html,SWebView,Context,jsObjectName)实例化LoginFrame登录页,调用LoginFrame.setVisible()方法更新视图。此时Login页面的JS脚本中触发LoginFrame.login_native()方法后,WebView会自动调用Java中LoginFrame对象的login_native()方法。判断登录成功后,使用4个参数的构造方法实例化MainFrame主界面(SWebView和Context与LoginFrame相同),同时调用MainFrame.setVisible()方法更新视图,便可使用MainFrame.execJS()在主界面执行JS脚本或者直接执行goBack()退出系统。使用流程如图6所示。
使用BaseFrame描述“窗口”对象,使页面资源模块化,功能内聚,降低耦合度, 开发者无需专注于资源整合,可以更专注于业务开发。
3.1改进框架
在Android4.4版本之后,WebView所有方法必须在同一线程中调用。而Android在MainActivity的onCreate方法中初始化WebView,WebView属于主线程。当JS脚本调用Java方法时,被调用的Java方法在子线程中执行,此时 Java方法调用主线程WebView的方法会显示“WebView方法在不同线程中调用”的异常,可能会引发应用程序崩溃(见图7)。
为此需要将WebView的所有方法同步调用,可使用Handler进行线程间通讯。将Handler初始化在主线程中,它与子线程可通过Message对象来传递数据。Handler接受子线程sendMessage()方法传入的Message对象(内含数据),将这些消息放入主线程的消息队列,配合主线程更新UI。Handler通讯如图8所示。
子线程Java中获取主线程的Handler后,使用Handler.sendMessage()方法向主线程Handler发送消息。主线程WebView中重写Handler消息队列的处理方法,给WebView的每个方法都构建相应的Handler调用方法,允许Handler接收到消息就转发,调用相应的WebView方法。但其缺陷也是显而易见的:调用一个WebView的方法就要单独构建一个Handler进行处理,代码冗余度和耦合度较高,可扩展性不强。
3.2使用“工厂”设计模式对Handler进行改进
为降低使用Handler通讯导致的高冗余度、高耦合度,基于“工厂”设计模式[7]结合Java反射技术,对Handler通讯进一步优化。在SWebView的Handler的消息处理方法中建立Method对象反射工厂。传入方法名、参数类型列表和参数即可自动生成相应的Method对象进行调用[8],如图9所示。
Java通过sendMessage()向主线程Handler消息队列发送需要调用的方法名、参数类型列表和具体参数。Handler不直接调用WebView的方法,由Method反射工厂生成Method对象进行调用,如图10所示。
基于Handler Method反射工厂的通讯模式,可有效降低模块耦合度和减少代码冗余,提高功能内聚,增强可扩展性和兼容性。最终系统架构如图11所示。
系统启动时在主线程的onCreate方法中初始化WebView设置,实例化首页的BaseFrame实现类。传入当前的WebView、Context、资源地址以及需注入的Java对象名后,APP首页即可完成绘制,在首页HTML的JS脚本中可随意调用已注入的Java对象, Java对象在子线程中处理业务逻辑后,调用BaseFrame相关方法,无需在不同线程操作WebView,即可完成JS与Java的交互闭环。
4结语
采用Android的Hybrid混合开发模式框架,基于装饰设计模式从显示层抽象设计BaseFrame,拥有较好的可扩展性和兼容性,有效降低了模块间的耦合度,提高了模块的健壮性和功能内聚性。使用Handler消息机制,解决Android4.4版本后关于WebView在不同线程调用引发异常问题。结合“工厂”设计模式和Java反射技术,建立Method对象反射工厂,保证框架良好的兼容性。经实际项目验证,本框架具有较高的扩展性及稳定性,为Android开发者提供了一个较好的Hybrid混合APP开发框架。
参考文献:
[1]周齐飞.基于Android平台的Hybrid App开发[J].电脑编程技巧与维护,2014(15):4648.
[2]宋小远,薛云志.一种Android平台混合应用运行环境[J].计算机系统应用,2016(9):98103.
[3]肖瑶.基于WebView的Android应用Web交互行为分析与研究[D].北京:北京邮电大学,2015.
[4]庞程,崔宣,粟潘,张永顺.基于Android平台HTML5的研究与实现[J].机械管理开发,2012(6):136137.
[5]史梦安,王志勃.基于Android系统的TCP/IP客户端异步通信模块研究[J].软件导刊,2014(10):115118.
[6]王芳,耿祥义,赵震.Java程序中的设计模式以及应用举例[J].电脑知识与技术,2007(8):438439.
[7]李文锦.Java程序中设计模式的抽取方法[D].长春:吉林大学,2005.
[8]张晶,王国明,许斌龙.Android系统环境下软件设计模式的研究[J].现代电子技术,2013(20)20:5153.
责任编辑(责任编辑:陳福时)