Worklight基于HTML5和JavaScript的跨平臺(tái)應(yīng)用
隨著智能手機(jī)和平板電腦的普及,越來越多的互聯(lián)網(wǎng) IT 企業(yè)把注意力集中到了移動(dòng)平臺(tái)上。目前市場上主流的移動(dòng)平臺(tái)有 Apple 的 iOS, Google 的 Android, 微軟的 Windows Phone, BlackBerry 以及 Nokia 的 Symbian 等。這些移動(dòng)平臺(tái)的開發(fā)環(huán)境和編程語言都不盡相同。同時(shí),一個(gè)平臺(tái)又有多個(gè)版本,例如 Android2.3 和 Android3.0 分別支持智能手機(jī)和平板電腦。正是由于這些多樣性,使得移動(dòng)應(yīng)用的開發(fā)存在成本高、周期長和維護(hù)困難等問題。
Worklight 是 IBM 收購的一套用于移動(dòng)應(yīng)用開發(fā)和基礎(chǔ)平臺(tái)整合的企業(yè)級(jí)解決方案。它支持多種移動(dòng)平臺(tái)的本地應(yīng)用開發(fā),同時(shí)也支持基于 HTML5 和 JavaScript 的跨平臺(tái)應(yīng)用。
本文主要介紹 Worklight 的 RuntimeSkin 特性以及如何使用該特性開發(fā)針對(duì)不同移動(dòng)終端的跨平臺(tái)應(yīng)用。
開發(fā)環(huán)境安裝與配置
Worklight 提供的是一整套移動(dòng)應(yīng)用的開發(fā)環(huán)境,涵蓋了從開發(fā)到集成,到管理、部署、監(jiān)控行等軟件開發(fā)生命周期的各個(gè)方面。它主要由四個(gè)部分組成,Worklight Studio、 Worklight Server、Device Runtime 和 Worklight Console:
- Worklight Studio 是基于 Eclipse 的集成開發(fā)環(huán)境,用戶可以很方便地創(chuàng)建、開發(fā)、部署和測(cè)試不同平臺(tái)的本地應(yīng)用或者混合型應(yīng)用。
- Worklight Server 是一個(gè)基于 Tomcat 的服務(wù)器,用于部署開發(fā)好的移動(dòng)應(yīng)用程序。同時(shí)它還提供適配器 (Adapter) 組件來進(jìn)行用戶登錄驗(yàn)證、后臺(tái)數(shù)據(jù)交互、消息推送等企業(yè)級(jí)應(yīng)用操作。
- Device Runtime 是 Worklight SDK 中包含一個(gè)組件,它主要提供了可以調(diào)用移動(dòng)平臺(tái)本地資源的多種接口,開發(fā)者可以使用 JavaScript API, 操作系統(tǒng)本地庫和第三方庫來調(diào)用這些接口,充分利用了本地應(yīng)用的優(yōu)點(diǎn)。
- Worklight Console 可以讓用戶通過瀏覽器來監(jiān)控、管理當(dāng)前部署在 Worklight Server 上的應(yīng)用程序和適配器組件。Worklight Console 同時(shí)還負(fù)責(zé)消息推送管理以及報(bào)表分析。
Worklight 開發(fā)環(huán)境的下載與安裝步驟可以從 developerWorks IBM Worklight 學(xué)習(xí)資源上獲得。
什么是運(yùn)行時(shí)皮膚(Runtime Skin)
運(yùn)行時(shí)皮膚是指 Worklight 的應(yīng)用程序可以為已經(jīng)創(chuàng)建好的手機(jī)平臺(tái)環(huán)境(Worklight Environment)添加多個(gè)皮膚,每一個(gè)皮膚是平臺(tái)環(huán)境的一個(gè)子集,所有的皮膚作為應(yīng)用程序的一部分打包在安裝文件中。當(dāng)應(yīng)用程序運(yùn)行時(shí)會(huì)根據(jù)具體 的移動(dòng)設(shè)備動(dòng)態(tài)地決定使用哪一個(gè)皮膚。運(yùn)行時(shí)皮膚的應(yīng)用場景有很多,比如不同的手機(jī)尺寸,不同的手機(jī)平臺(tái)版本,是否支持 HTML5 等等。
下面我們以一個(gè)新聞瀏覽的應(yīng)用程序?yàn)槔?,具體介紹如何應(yīng)用 Worklight 的 Runtime Skin 特性。
創(chuàng)建 Worklight 工程和應(yīng)用程序
- 我們創(chuàng)建一個(gè) Worklight 工程。在 Eclipse 中選擇 File->New->Worklight Project, 如圖 1 所示。
圖 1. 創(chuàng)建 Worklight 工程
- 輸入工程名稱 Mobile News。接著我們創(chuàng)建一個(gè) Worklight 應(yīng)用程序,選擇 File->New->Worklight Application,如圖 2 所示。
圖 2. 創(chuàng)建 Worklight 應(yīng)用程序
- 在彈出的窗口中選擇***步新建的工程,然后輸入應(yīng)用程序的名稱 NewsApp,如圖 3 所示。
圖 3. 在工程中創(chuàng)建應(yīng)用程序
- 創(chuàng)建完工程和應(yīng)用程序以后,Worklight 會(huì)自動(dòng)生成如下的目錄結(jié)構(gòu),如圖 4 所示。
圖 4. 應(yīng)用程序目錄結(jié)構(gòu)
我們看到在 apps 目錄下包含剛剛創(chuàng)建的應(yīng)用程序 NewsApp,初始情況下每一個(gè)應(yīng)用程序會(huì)有一個(gè) common 的運(yùn)行時(shí)環(huán)境,它會(huì)被不同手機(jī)平臺(tái)環(huán)境(例如 iOS, Android, BlackBerry 等)所共用。在 common 文件夾下有三個(gè)文件夾 css, images 和 js,分別存放了程序相關(guān)的 css 文件,圖片和 JavaScript 文件。NewsApp.html 是程序自動(dòng)創(chuàng)建的主 html 文件。
在工程中引入 Dojo Mobile
在這個(gè)例子中,我們使用 Dojo Mobile 做為手機(jī)界面開發(fā)的 JavaScript 框架。Dojo Mobile 是 Dojo JavaScript 的一個(gè) mobile 版本擴(kuò)展,專門為手機(jī)移動(dòng)開發(fā)提供很多豐富的控件和不同的 css 主題。
打開 NewsApp.html,在 head 中引用 dojo.js 文件,這里我們使用 CDN 的方式,如清單 1 所示。讀者也可以從 dojo 的官方網(wǎng)站上下載 dojo toolkit 包,拷貝到工程里,然后在 html 文件中引用 dojo.js。
清單 1. 引用 dojo.js
- <script type="text/javascript"
- data-dojo-config="isDebug: false, async: true, parseOnLoad: true"
- src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js">
- </script>
- 在 js/NewsApp.js 的 wlCommonInit() 初始化函數(shù)中添加相應(yīng)的 dojo mobile 模塊,這里我們用到的是 AMD 方式,當(dāng) require 方法加載完所需的 dojo mobile 模塊以后,會(huì)調(diào)用 init 這個(gè)初始化函數(shù),函數(shù)具體的實(shí)現(xiàn)放在運(yùn)行時(shí)皮膚。
清單 2. 用 AMD 方式加載 dojo mobile 模塊
- require([
- "dojo",
- "dojox/mobile/parser",
- "dojox/mobile",
- "dojox/mobile/compat",
- ], function(dojo) {
- dojo.ready(function() {
- init();
- });
- });
定義視圖
這個(gè)示例程序一共分為兩個(gè)視圖:***個(gè)視圖是列表視圖,展示多條新聞的標(biāo)題。第二個(gè)視圖是正文視圖,顯示新聞的正文。兩個(gè)視圖的交互方式分為兩種, ***種方式是首頁顯示列表視圖,當(dāng)用戶點(diǎn)擊某一個(gè)新聞標(biāo)題后,轉(zhuǎn)到正文視圖。點(diǎn)擊正文視圖左上角的返回按鈕,返回到列表視圖,如圖 5 左側(cè)所示。這種方式適合小屏幕的手機(jī)。
第二種方式是把列表視圖和正文視圖顯示在同一個(gè)頁面中,如圖 5 右側(cè)所示。頁面左側(cè)是新聞列表視圖,頁面右側(cè)是正文視圖。用戶可以在列表視圖中選擇新聞標(biāo)題,相應(yīng)的新聞?wù)木蜁?huì)在右側(cè)顯示。這種方式適合在平板電腦這種屏幕較大的移動(dòng)設(shè)備上。
圖 5. 兩種顯示方式
在新建皮膚之前,我們需要把不同皮膚共用的代碼放在 common 環(huán)境中。
- 首先在 common 環(huán)境下新建一個(gè) data 文件夾來存放兩個(gè)視圖的模版,分別命名為 list.html 和 detail.html.
清單 3. 列表視圖代碼 - <h1 id="listHead" data-dojo-type="dojox.mobile.Heading" label="News"></h1>
- <ul id="newsList" data-dojo-type="dojox.mobile.EdgeToEdgeList">
- <li data-dojo-type="dojox.mobile.ListItem" moveTo="detailView"
- label="news 1 title"></li>
- <li data-dojo-type="dojox.mobile.ListItem" moveTo="detailView"
- label="news 2 title"></li>
- </ul>
清單 4. 正文視圖代碼- <h1 id="detailHead" data-dojo-type="dojox.mobile.Heading" label="News title"></h1>
- <div data-dojo-type="dojox.mobile.RoundRect" data-dojo-props='shadow:true'>
- <p>This is news body</p>
- </div>
- 在 common/js 中添加通用的 javscript 方法。
清單 5. loadView 方法- function loadView(id, url) {
- var view = new dojox.mobile.ScrollableView({
- id: id,
- selected: true
- });
- var contentPane = new dojox.mobile.ContentPane({
- href: url
- });
- view.addChild(contentPane);
- return view;
- }
loadView 方法主要工作是把列表視圖(list view)和正文視圖(detail view)分別加載到一個(gè) ScrollableView 當(dāng)中。接下來我們開始創(chuàng)建兩個(gè)不同的皮膚以及皮膚相關(guān)的代碼。
創(chuàng)建運(yùn)行時(shí)皮膚
首先我們需要新建一個(gè) Worklight 環(huán)境,右鍵 NewsApp 工程選擇 New ->Worklight Environment, 如圖 6 所示。
圖 6. 創(chuàng)建 Worklight 環(huán)境
Worklight 提供了多種手機(jī)平臺(tái)環(huán)境,包括:iPhone/iPad, Android, BlackBerry 和 Windows Phone 等。在這里我們選擇 Android phones and tablets,如圖 7 所示。
圖 7. 添加 Android phone and tablet 環(huán)境
接下來我們創(chuàng)建兩套運(yùn)行時(shí)皮膚,一套針對(duì) Android 手機(jī),另外一套針對(duì) Android 平板電腦。
右鍵 NewsApp 項(xiàng)目,選擇 New -> Worklight Application Skin, 然后選擇 Skin 對(duì)用的手機(jī)環(huán)境為之前創(chuàng)建的 Android phones and tablets, 輸入 skin 的名字 android.phone, 如圖 8 所示。
圖 8. 添加 Android Phone 皮膚
同樣地,我們創(chuàng)建另外一個(gè)皮膚,名稱為 android.tablet. Worklight 會(huì)自動(dòng)地將創(chuàng)建完的皮膚在 application-descriptor.xml 中注冊(cè),如清單 6 所示。這里需要注意一點(diǎn),當(dāng)我們刪除某一個(gè) skin 的時(shí)候,需要在 application descriptor 中手動(dòng)刪除該 skin 標(biāo)簽。
清單 6. application-descriptor.xml 中注冊(cè)的 skin 信息
- <android version="1.0">
- <skins>
- <skin name="default">
- <folder name="common"/>
- <folder name="android"/>
- </skin>
- <skin name="android.phone">
- <folder name="common"/>
- <folder name="android"/>
- <folder name="android.phone"/>
- </skin>
- <skin name="android.tablet">
- <folder name="common"/>
- <folder name="android"/>
- <folder name="android.tablet"/>
- </skin>
- </skins>
- </android>
每一個(gè)皮膚包含了各自的 css 文件,image 圖片和 javascript 方法。我們需要為兩個(gè)皮膚創(chuàng)建不同的初始化函數(shù),把列表視圖和正文視圖按照特定的方式加載到主 html 文件中。
- 在 android.phone 的 js 文件夾下新建一個(gè)與 common/js 下同名的 js 文件:NewsApp.js,在這個(gè)文件里添加初始化函數(shù)。
清單 7. phone 皮膚的初始化函數(shù) - function init() {
- var listView = loadView("listView", "data/list.html");
- dojo.place(listView.domNode, dojo.body());
- var detailView = loadView("detailView", "data/detail.html");
- dojo.place(detailView.domNode, dojo.body());
- }
初始化函數(shù)把兩個(gè)視圖按順序添加到主頁面中,當(dāng)程序啟動(dòng)時(shí),顯示***個(gè)頁面,也就是列表視圖。當(dāng)用戶點(diǎn)擊列表視圖中的某一項(xiàng),就會(huì)轉(zhuǎn)到正文視圖。
- 同樣地,我們?cè)?android.tablet 的 js 文件夾下也新建一個(gè) NewsApp.js,它的初始化函數(shù)如下:
清單 8. tablet 皮膚的初始化函數(shù) - function init() {
- var fixedSplitter = new dojox.mobile.FixedSplitter({
- orientation: "H"
- }, dojo.create("div", null, dojo.body(), 'first'));
- fixedSplitter.startup();
- var listView = loadView("listView", "data/list.html");
- var leftPane = new dojox.mobile.ContentPane({
- id: "leftPane",
- content: listView.domNode
- });
- fixedSplitter.addChild(leftPane);
- var detailView = loadView("detailView", "data/detail.html");
- var rightPane = new dojox.mobile.ContentPane({
- id: "rightPane",
- content: detailView.domNode
- });
- fixedSplitter.addChild(rightPane);
- }
在這個(gè)初始化函數(shù)中,我們用到了 FixedSplitter 這個(gè) dojo mobile 控件,它可以把 mobile 頁面分為多個(gè)區(qū)域,每個(gè)區(qū)域可以加載不同的視圖。這里我們把整個(gè)頁面分成左右兩塊 leftPane 和 rightPane,分別加載列表視圖和正文視圖。
當(dāng)我們完成不同皮膚的初始化函數(shù)之后,需要在 skinLoader.js 的 getSkinName 方法中添加根據(jù)移動(dòng)設(shè)備屏幕大小動(dòng)態(tài)選擇皮膚的代碼。如圖 9 所示。
圖 9. skinLoader.js
清單 9. getSkinName 方法
- function getSkinName() {
- var skinName = "android.phone";
- var screenHeight = screen.height;
- var screenWidth = screen.width;
- if (screenHeight >= 1000 || screenWidth >= 1000) {
- skinName = "android.tablet";
- }
- return skinName;
- }
這個(gè)方法根據(jù)屏幕的大小來選擇應(yīng)用哪一個(gè)皮膚。注意 skinName 的值要跟創(chuàng)建的皮膚名稱保持一致。
皮膚應(yīng)用效果
我們把 NewsApp 工程部署到 Worklight Server 上,然后分別在不同手機(jī)尺寸的模擬器上運(yùn)行。圖 10 所示的是運(yùn)行在小屏幕手機(jī)上的效果。圖 11 所示的是運(yùn)行在大屏幕平板電腦上的效果。
圖 10. 手機(jī)顯示效果
圖 11. 平板電腦顯示效果
結(jié)束語
運(yùn)行時(shí)皮膚是 Worklight 的一個(gè)重要特性,它可以方便地在同一個(gè)應(yīng)用程序中添加多個(gè)皮膚外觀,在程序運(yùn)行時(shí)動(dòng)態(tài)地選擇適合移動(dòng)終端設(shè)備的皮膚。本文從一個(gè)具體的實(shí)例出發(fā),幫助讀者了解運(yùn)行時(shí)皮膚的具體使用方法。