自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

移動(dòng)開發(fā)中如何整合HTML 5和原生代碼

譯文
移動(dòng)開發(fā)
使用HTML 5開發(fā)應(yīng)用比起為每一種不同的平臺(tái)從頭開始編寫代碼,是一種能跨不同平臺(tái)而代碼量較少的一種方式。在這種情況下,大部分的用戶界面,甚至全部的界面都可以通過HTML 實(shí)現(xiàn)。

最近業(yè)界關(guān)于移動(dòng)開發(fā)中的究竟使用原生代碼還是HTML 5代碼的爭論依然持續(xù)。目前來說有三種方式去進(jìn)行移動(dòng)開發(fā)

•    原生代碼,
•    hybrid(混合型)移動(dòng)應(yīng)用
•    移動(dòng)Web app(使用HTML5)
使用HTML 5開發(fā)應(yīng)用比起為每一種不同的平臺(tái)從頭開始編寫代碼,是一種能跨不同平臺(tái)而代碼量較少的一種方式。在這種情況下,大部分的用戶界面,甚至全部的界面都可以通過HTML 實(shí)現(xiàn)。

“Hybrid應(yīng)用”一詞,指的是移動(dòng)應(yīng)用大部分是用HTML 5去編寫界面,而部分需要訪問特定設(shè)備功能的則使用原生代碼。大部分這些原生代碼并不是自然生成可視的,而僅僅通過特定的轉(zhuǎn)換將數(shù)據(jù)返回給應(yīng)用的HTML 5界面,再經(jīng)過渲染返回給用戶。PhoneGap這個(gè)框架就提供了這樣的功能。

[[88958]]

大部分關(guān)于HTML 5的爭論并不是著眼于討論它是否能勝任移動(dòng)應(yīng)用中的用戶體驗(yàn)。Facebook創(chuàng)始人 Mark Zuckerberg在他的對Facebook在使用HTML 5中遇到的困難一文中作了相關(guān)評論。Facebook的一些問題可以通過由Sencha Touch框架進(jìn)行解決(參考SenchaTouch自己的一個(gè)例子Fastbook),也可以通過LinkedIn在其infinite scrolling post一文中解決。此外,LinkedIn隨后還提供了使用更多的原生代碼解決關(guān)于轉(zhuǎn)換方向的問題。

為何不進(jìn)行整合?

與其使用全部的原生代碼或者HTML 5代碼去開發(fā),為什么不將兩者進(jìn)行整合呢?使用混合型開發(fā)移動(dòng)應(yīng)用,可以同時(shí)利用原生和HTML 5代碼開發(fā)用戶界面。這就能讓開發(fā)者在設(shè)計(jì)用戶界面的時(shí)候能使用最適合的工具。

很明顯,對于開發(fā)用戶應(yīng)用界面使用兩種或者更多的技術(shù)是有其缺點(diǎn)的。最重要的是必須讓開發(fā)者既掌握原生的開發(fā)又掌握HTML 5。使用原生代碼開發(fā)的用戶界面不大容易在其他平臺(tái)使用,并需要重新開發(fā)。由于這些技術(shù)需要更廣泛的知識(shí)面和上面提到的困難,為什么還有人嘗試努力使用這它?

HTML 富文檔界面

可能你的用戶體驗(yàn)告訴你文檔可以以富文本格式進(jìn)行顯示更為精彩。雖然在iOS上可以使用NSAttributedString進(jìn)行富本文格式化,但這種文檔的結(jié)構(gòu)并不適合遷移到其他設(shè)備平臺(tái)中,也不能完整由HTML再現(xiàn)。如果文檔中需要使用如表格進(jìn)行顯示,則象NSAttributedString的解決方案是不能奏效的。考慮下面的一家基因檢測公司的iPad應(yīng)用,如下圖,是一個(gè)混合型界面的例子:

請注意看上面的圖,很難從表面上分辨這到底哪部分是用原生代碼編寫的,哪部分是用HTML 5編寫的。這個(gè)界面中的右邊部分是可變的長度。表格是包含可擴(kuò)展的行,完全使用CSS3動(dòng)畫效果,而頁面中其他文字部分都是相同的高度。

Documents such as this are what HTML does best. Trying to create something like this in native code would have entailed considerably greater effort, with little benefit to the user. In this application, the HTML5 is generated with a mustache template, via theGRMustache library for iOS.

像這樣的頁面使用HTML 5實(shí)現(xiàn)是最好的。如果嘗試使用原生代碼去實(shí)現(xiàn)則要花費(fèi)很大功夫,而且對用戶好處不多。在這個(gè)應(yīng)用中,通過使用為iOS而設(shè)的GRMustache類庫去生成相關(guān)的HTML 5模板。下圖中用顏色區(qū)別表明了哪個(gè)部分是使用HTML5,哪個(gè)部分使用原生代碼。

注意當(dāng)用戶移動(dòng)滾動(dòng)條的時(shí)候,在右側(cè)頂部的文檔頭部會(huì)動(dòng)態(tài)改變大小以顯示更多的內(nèi)容,從而說明用戶界面之間是如何互動(dòng)的。用戶可以點(diǎn)在HTML 5實(shí)現(xiàn)部分的連接和按鈕,以彈出一個(gè)內(nèi)置的Web瀏覽器以加載相關(guān)內(nèi)容。在本文接下來的部分,會(huì)看到在原生代碼的界面和HTML 5的界面之間互相連接是很容易的事情。

兩全其美的解決方法

正如我們所看到的,可以在同一個(gè)應(yīng)用的屏幕中整合兩種不同的技術(shù)以提供無縫的體驗(yàn)。你可能希望在iOS上使用UINavigationController和與之相關(guān)的 UINavigationBar控件,或者在Android應(yīng)用中使用action bar,而剩下的部分則使用HTML 5渲染。

下面是一個(gè)使用HTML 5設(shè)計(jì)的購物車應(yīng)用體驗(yàn),但依然有保留原生的導(dǎo)航控件和用于頁面導(dǎo)航的tab工具條:

這里,HTML 5內(nèi)容實(shí)際上是從服務(wù)端加載的,它在整個(gè)用戶體驗(yàn)中控制著流程。有相關(guān)的API允許服務(wù)端生成的HTML去修改導(dǎo)航控件中的內(nèi)容以適應(yīng)瀏覽的過程。

你可能會(huì)發(fā)現(xiàn)原生的控件,如iOS中的MapKit等都提供了比HTML 5控件更好的性能體驗(yàn),在這種情況下,應(yīng)該使用HTML 5代碼去和iOS原生代碼層通信,讓其返回內(nèi)容并呈現(xiàn)。

上面的兩個(gè)圖描述了一個(gè)綜合運(yùn)用原生和HTML 5的購物應(yīng)用。用戶首先在地圖中選擇了商店地址,然后數(shù)據(jù)將已HTML 5的方式呈現(xiàn),用戶并繼續(xù)購物。

一旦用戶完成了和地圖的交互,結(jié)果則會(huì)馬上傳遞到HTML 5頁面中以作進(jìn)一步處理。原生“控件”可以在任何平臺(tái)(iOS、Android、Windows等)中實(shí)現(xiàn),這取決于應(yīng)用是如何架構(gòu),并且能從HTML5應(yīng)用中調(diào)用。使用這個(gè)策略,HTML 5代碼將提供對整個(gè)應(yīng)用流程的控制,而原生代碼則在后臺(tái)運(yùn)行等到需要的時(shí)候提供數(shù)據(jù),如果處理恰當(dāng),用戶是很難區(qū)分應(yīng)用的哪一個(gè)部分是使用HTML5,哪一個(gè)部分是使用原生代碼。

#p#

更容易的應(yīng)用更新

大多數(shù)人都知道為了在iOs或者Android應(yīng)用中更新應(yīng)用,都必須重新通過相應(yīng)平臺(tái)正常的渠道去重新提交。對于Ios,可能需要等待七天去獲得蘋果的批準(zhǔn),這就很難在當(dāng)今移動(dòng)應(yīng)用的狂潮中滿足用戶的迫切需要。如果通過HTML和Javascript的方法去給用戶移動(dòng)體驗(yàn),則意味著可以通過Web去動(dòng)態(tài)滿足用戶的需要。

正如前文說的,由于可以通過Web的方法調(diào)用應(yīng)用中的原生代碼,則看上去這其實(shí)是一種”橋梁”的機(jī)制。PhoneGap就是通過PhoneGap plugin interface去實(shí)現(xiàn)。之前的購物商店的例子就是使用這個(gè)方法。使用這個(gè)方法可以使得購物的流程如果改變后不再需要走繁瑣的原生應(yīng)用的發(fā)布流程。如果一個(gè)設(shè)計(jì)良好的界面可以使得頁面和原生容器之間的通訊變?yōu)榭赡堋?/p>

關(guān)于內(nèi)容方面

對于來自Web的內(nèi)容,通常最好能限制其通過這種橋接技術(shù)的流量。類似PhoneGap的內(nèi)置的功能提供了很多設(shè)備的信息,其中一些可能會(huì)遠(yuǎn)遠(yuǎn)超出應(yīng)用程序的所需要。如果由于某種原因Web內(nèi)容被泄露,比如跨站點(diǎn)腳本攻擊,你可能會(huì)突然發(fā)現(xiàn)這些內(nèi)容會(huì)以某種方式調(diào)用本地代碼。

基于這個(gè)原因,當(dāng)需要使用混合型移動(dòng)應(yīng)用的時(shí)候,應(yīng)該使用你自己的橋接代碼,以嚴(yán)格控制哪些代碼可以動(dòng)態(tài)加載什么樣的內(nèi)容。一些平臺(tái)有自己的控制方法去限制從Web viewer中對原生代碼的調(diào)用。在Android中,類必須明確自己注冊通過JavaScript訪問。在Android 4.2中,可以進(jìn)一步通過在需要從Web viewer中訪問的方法前添加@ JavaScriptInterface注解去限制其調(diào)用。

需要考慮的要點(diǎn)

•     如果用戶在線,直接從Web服務(wù)器容是很好的。請記住,移動(dòng)應(yīng)用的網(wǎng)絡(luò)連接問題。如果網(wǎng)絡(luò)連接中斷,會(huì)發(fā)生什么事? 有的時(shí)候可以通過AppCache實(shí)現(xiàn)一些離線功能,但這需要規(guī)劃。另一種方法在稍后介紹,使用的是本地存儲(chǔ)。

•     托管在Web服務(wù)器上的內(nèi)容需要一定的基礎(chǔ)設(shè)施。現(xiàn)在有更多的需要被視為移動(dòng)應(yīng)用組成部分的“組件”。它不再僅僅是一些通過AppStore部署的原生代碼和一些后端的服務(wù)。必須小心的是在網(wǎng)站更新的時(shí)候,不要移動(dòng)應(yīng)用程序與現(xiàn)有的接口間發(fā)生沖突。請記住,網(wǎng)站的內(nèi)容發(fā)生了變化,則必須更新移動(dòng)應(yīng)用程序本身。出于這個(gè)原因,可能需要對網(wǎng)站的內(nèi)容進(jìn)行必要的版本標(biāo)記以區(qū)分其內(nèi)容。

•   
蘋果公司對僅僅包裹在原生應(yīng)用中的Web view這樣類型的應(yīng)用持悲觀看法。如果你只是在一個(gè)原生移動(dòng)應(yīng)用中,僅僅包含一些Web內(nèi)容,則可能在提交iOS的AppStore審批時(shí)不會(huì)得到批準(zhǔn)。蘋果公司希望你的應(yīng)用程序?qū)⑹褂玫囊恍┰O(shè)備自身的功能,或者好歹使用下Mobile Safari。。想想看,你的應(yīng)用程序其實(shí)可以集成相機(jī)功能、聯(lián)系人列表、本地?cái)?shù)據(jù)存儲(chǔ),離線操作等,還要記得,這些Web view中提供的內(nèi)容必須和原來應(yīng)用提交的樣式等保持一致。

如果你創(chuàng)建了一個(gè)詞搜索游戲,然后突然開始在webview瀏覽器中有一些風(fēng)馬牛不相及的內(nèi)容,這將違反蘋果的條款,并可能在AppStore中下架。根據(jù)iOS開發(fā)者協(xié)議,每次的更新不能改變在提交appStore審核時(shí)闡述的該應(yīng)用的主要功能。

體驗(yàn)應(yīng)用更新過程

正如上文提到的,從web服務(wù)器加載內(nèi)容再刷新本地的內(nèi)容。在這種方法中,只要web內(nèi)容更新,服務(wù)器上的Web內(nèi)容(HTML,CSS和JavaScript)會(huì)下載到移動(dòng)應(yīng)用程序客戶端。更新代碼就可以改變用戶的界面,應(yīng)用流程等,這無需開發(fā)人通過使用iOS App Store或Google Play去處理。

注意的是只能更新HTML、CSS和Javascript,是不能更新原生代碼的。蘋果公司允許只要在iOs應(yīng)用中在UIWebView控件的上下文中運(yùn)行就可以下載Javascript。

上圖的應(yīng)用是運(yùn)行在Android中。HTML的內(nèi)容是下載到用戶的移動(dòng)設(shè)備中并存儲(chǔ)的。注意應(yīng)用提供了導(dǎo)航條的用戶體驗(yàn)。下圖則是運(yùn)行在iOs的情景,使用的是UINavigationController :

除了加快更新過程,這種傳輸應(yīng)用程序的方式能確保用戶獲得最新的代碼。在傳統(tǒng)的方法中,應(yīng)用程序的更新是通過應(yīng)用程序商店分發(fā),并通知用戶有可用的更新,盡管他們并不需要安裝最新的更新。不是每個(gè)人都定期去更新應(yīng)用程序。而在用戶瀏覽應(yīng)用的時(shí)候,通過更新本地的HTML,CSS和JavaScript正好解決這個(gè)問題。

動(dòng)態(tài)更新本地內(nèi)容的功能,實(shí)際上是商業(yè)混合型移動(dòng)應(yīng)用開發(fā)平臺(tái)“Trigger.IO”的一部分。 Trigger.IO功能允許更新你移動(dòng)應(yīng)用的HTML部分。需要注意的是原生代碼不能以這種方式更新。但是,如果你應(yīng)用程序的流程控制使用的JavaScript和增強(qiáng)的本機(jī)代碼,那么應(yīng)用程序流程作發(fā)生變化的時(shí)候同步更新是可能的。

動(dòng)態(tài)更新內(nèi)容對開發(fā)和測試的好處

能動(dòng)態(tài)更新一個(gè)移動(dòng)應(yīng)用,也可以加速開發(fā)進(jìn)程。 iOS和Android的原生開發(fā)過程一般需要在桌面計(jì)算機(jī)上對應(yīng)用程序代碼進(jìn)行編譯,然后轉(zhuǎn)移到測試設(shè)備中去。一些發(fā)開發(fā)者項(xiàng)目,如Icenium、LiveSync或Ion則支持編譯應(yīng)用的更新到云端,然后只需下載已經(jīng)在設(shè)備上運(yùn)行的應(yīng)用程序,這就完成了更新。

當(dāng)代碼進(jìn)行了更改,并保存到服務(wù)器上,只需要一個(gè)簡單的三個(gè)手指頭的手勢動(dòng)作就可以更新iOS設(shè)備上的應(yīng)用程序。 Icenium也有類似的功能并可用于Android。 Adobe公司的PhoneGap通過一個(gè)被稱為Hydration的特性讓更新變得可能。在這種情況下,開發(fā)人員可以通過他們的IDE整合到各種設(shè)備上,而無需物理連接到這些移動(dòng)設(shè)備,就可以推送新的代碼。

當(dāng)Hydration功能啟用的時(shí)候,每次啟動(dòng)應(yīng)用程序時(shí),應(yīng)用程序?qū)z查PhoneGap構(gòu)建服務(wù)器去看是否有新版本可用。如果有,用戶將被提示升級到新的版本。這可以使你的應(yīng)用程序的質(zhì)量得到保證,以及更容易使用。你將不必?fù)?dān)心簽署代碼更新、配置和測試等問題。

#p#

注意事項(xiàng)

雖然動(dòng)態(tài)更新應(yīng)用的功能很強(qiáng),但記住并確保凡是來源于網(wǎng)絡(luò)的內(nèi)容必須不能隨意調(diào)用設(shè)備的原生代碼。如果不這樣做,可能會(huì)導(dǎo)致你的用戶數(shù)據(jù)暴露給第三方,因此違反與蘋果或Google的協(xié)議。此外,動(dòng)態(tài)更新內(nèi)容不應(yīng)該改變應(yīng)用原來的功能。否則會(huì)可能被蘋果或者Google下架應(yīng)用。

溝通兩個(gè)世界的橋梁

iOS和Android都提供了能在原生應(yīng)用中使用的Web view控件,接下來的例子中將講解如何在Web view中使用Javascript調(diào)用原生代碼以及原生代碼如何調(diào)用在Web view中的Javascript。

[[88959]]

首先你必須使用PhoneGap(Apache Cordova),可以使用PhoneGap 1.4 for iOS 和PhoneGap 1.9 for Android。本文并不從PhoneGap的基礎(chǔ)開始講解,因此讀者可能需要到PhoneGap官網(wǎng)了解一些相關(guān)知識(shí)。對于iOs可以將CordovaWebView 放到原生的viewController控件中,而Android中也可以使用。這允許你的web代碼能訪問整個(gè)PhoneGap API并且訪問任何PhoneGap插件。當(dāng)然可以根據(jù)PhoneGap plugin API 去將應(yīng)用的原生代碼暴露給CordovaWebView。

假設(shè)你不需要使用PhoneGap的全部功能而只是需要在原生和HTML5兩個(gè)世界中使用它們部分的功能,則也可以自己去編寫代碼是實(shí)現(xiàn)這個(gè)橋梁。本文之前提到的三個(gè)應(yīng)用都是使用“私有API”的方式去實(shí)現(xiàn)編碼的。

研究iOS中的UIWebView

在iOS中的UIWebView和相關(guān)的UIWebViewDelegate提供了相關(guān)的機(jī)制,并允許原生代碼和Javascript之間互相調(diào)用,下面準(zhǔn)備了一個(gè)簡單的例子進(jìn)行講解:

注意屏幕中的上半部分,淺灰色部分使用的是UIWebView進(jìn)行渲染,而下半部分白色的使用的是原生代碼聲稱的。這個(gè)應(yīng)用只是從Web view中傳遞JSON對象到原生代碼中,反之亦然,代碼和Android版本的可以在 這個(gè)地址下載:
https://github.com/ptraeg/html5-in-mobile-apps

從Javascript中調(diào)用原生代碼

從Javascript中去調(diào)用原生代碼很簡單,只是在方法中帶有command和以JSON格式要傳遞的參數(shù),代碼如下:

  1.  var nativeBridge = { 
  2.    invoke: function (commandName, args) { 
  3.       console.log(commandName + ": " + JSON.stringify(args, null, 2)); 
  4.       window.location = 'js-call:' + commandName + ':' + 
  5.                       encodeURIComponent(JSON.stringify(args)); 
  6.   } 
  7. }; 


上面的代碼嘗試去將瀏覽器導(dǎo)航到一個(gè)新的URL,但并不是用傳統(tǒng)的http://或file://的URL。這里使用的是自定義協(xié)議js-call:,而在Objective-C方面,代碼如下:

 

  1. (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType (UIWebViewNavigationType)navigationType 

在這個(gè)調(diào)用的委托中,可以查詢傳入的URL是否是來自Javascript的調(diào)用:

 

  1. NSString *requestURLString = [[request URL] absoluteString]; 
  2. f ([requestURLString hasPrefix:@"js-call:"]) { 

接下來是判斷command的名字和JSON參數(shù)字符串:

 

  1.  NSArray *components = [requestURLString componentsSeparatedByString:@":"]; 
  2. NSString *commandName = (NSString*)[components objectAtIndex:1]; 
  3. NSString *argsAsString = [ (NSString*)[components objectAtIndex:2] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]; 

 既然我們將參數(shù)作為字符串,則可以將其轉(zhuǎn)換為NSDictionary對象:

 

  1.  NSError *error = nil; 
  2. NSData *argsData = [argsAsString dataUsingEncoding:NSUTF8StringEncoding]; 
  3. NSDictionary *args = (NSDictionary*)[NSJSONSerialization JSONObjectWithData:argsData options:kNilOptions error:&error]; 

最后,是時(shí)候調(diào)用正確的原生方法以處理Javascript調(diào)用的參數(shù)并且刷新原生UI:

 

  1. if ([commandName isEqualToString:@"updateNames"]) { 
  2.    [self updateNativeNameValuesWithFirstName:[args objectForKey:@"fname"
  3.                                     LastName:[args objectForKey:@"lname"]]; 

記得在通過js-call調(diào)用方法的時(shí)候,必須從委托中返回boolean值為no,以防止Web view嘗試訪問URL。

#p#

iOS原生代碼中訪問Javascript

這種方法比較簡單,因?yàn)槲覀儧]有使用委托方法。我們可以簡單通過傳入要調(diào)用的JavaScript函數(shù)名和需要的參數(shù)作為字符串,傳給UIWebView的stringByEvaluatingJavaScriptFromString方法就可以了
在這里,我們從本地視圖中獲得值并且通過NSDictionary將其變成一個(gè)JSON對象。

 

  1.  NSDictionary *namesDict = @{@"fname": self.fNameTextField.text,  
  2.                             @"lname": self.lNameTextField.text}; 
  3. NSError *error; 
  4. NSData *namesData = [NSJSONSerialization dataWithJSONObject:namesDict  
  5.                                                     options:0  
  6.                                                       error:&error]; 
  7. NSString *namesJSON = [ [NSString alloc] initWithData:namesData 
  8.                                              encoding:NSUTF8StringEncoding] ; 

既然已經(jīng)將JSON作為字符串傳遞,只需要格式化命令并傳遞到Web view中就可以了。

 

  1. NSString *jsCommand = [NSString stringWithFormat:@"setNames(%@)", namesJSON]; 
  2. [self.webView stringByEvaluatingJavaScriptFromString:jsCommand]; 

在Android中使用Webview

同樣,下圖是使用Android的Webview實(shí)現(xiàn)上面iOS例子的效果:

同樣,上部分灰色的是由Web View生成的,下半部分的是原生代碼生成。

從Javascript代碼中調(diào)用原生代碼

Android Web VIEW有個(gè)好處就是能將全部的Java類暴露給Javascript,這就不用象iOS那么麻煩了。首先只需要對Android Web view進(jìn)行注冊設(shè)置就可以了,代碼如下:

 

  1. @Override 
  2. public void onStart() { 
  3.    super.onStart(); 
  4.    WebSettings webSettings = webview.getSettings(); 
  5.    webSettings.setJavaScriptEnabled(true); 
  6.    webview.loadUrl("file:///android_asset/webviewContent.html"); 
  7.    webview.addJavaScriptInterface(new WebViewInterface(this), "Android"); 

注意上面最后一行代碼,注冊了一個(gè)特殊的類名為WebViewInterface,它可以通過Javacript去訪問,此外,該類還通過字符串“Android”指出其命名空間,還可以測試是否注冊了Android命名空間,代碼為:

 

  1. if (window.Android) { 
  2.    Android.updateNames(JSON.stringify(nameData)); 

而在Java服務(wù)端,WebViewInterface是一個(gè)標(biāo)準(zhǔn)的Java類,如果使用的是Android 4.2 SDK,則必須使用@JavaScriptInterface去注解要暴露給Javascript的方法。

 

  1. public class WebViewInterface { 
  2.    Context mContext; 
  3.  
  4.    /** Instantiate the interface and set the context */ 
  5.    WebViewInterface(Context c) { 
  6.        mContext = c; 
  7.    } 
  8.  
  9.    @JavaScriptInterface 
  10.    public void updateNames(String namesJsonString) { 
  11.       Log.d(getPackageName(), "Sent from webview: " + namesJsonString); 
  12.       try { 
  13.          JSONObject namesJson = new JSONObject(namesJsonString); 
  14.          final String firstName = namesJson.getString("fname"); 
  15.          final String lastName = namesJson.getString("lname"); 
  16.  
  17.          // When invoked from JavaScript, this is executed on a thread  
  18.          // other than the UI thread. 
  19.          // Because we want to update the native UI controls, we must  
  20.          // create a runnable for the main UI thread. 
  21.          runOnUiThread(new Runnable() { 
  22.             public void run() { 
  23.                fnameEditText.setText(firstName); 
  24.                lnameEditText.setText(lastName); 
  25.              } 
  26.          }); 
  27.       } catch (JSONException e) { 
  28.          Log.e(getPackageName(),  
  29.             "Failed to create JSON object from Web view data"); 
  30.       } 
  31.    } 

注意當(dāng)Javascript調(diào)用這個(gè)類中的方法的時(shí)候,它們并不是在主UI 線程中執(zhí)行的,如果我們的目的是更新UI部分,則必須創(chuàng)建新的runnable線程并且傳遞給主UI線程執(zhí)行:

 

  1. runOnUiThread(new Runnable() { 
  2.    public void run() { 
  3.       fnameEditText.setText(firstName); 
  4.       lnameEditText.setText(lastName); 
  5.    } 
  6. }); 

而在原生代碼中調(diào)用Javascript則比較簡單。將數(shù)據(jù)用JSON的形式存放到字符串中然后就可以給Javascript調(diào)用,注意要使用的是Javascript:協(xié)議:

 

  1. public void sendNamesToWebView() { 
  2.    JSONObject namesJson = new JSONObject(); 
  3.    try { 
  4.       namesJson.put("fname", fnameEditText.getText().toString()); 
  5.       namesJson.put("lname", lnameEditText.getText().toString()); 
  6.       webview.loadUrl( "JavaScript:setNames(" + namesJson.toString() + ")" ); 
  7.    } catch (JSONException e) { 
  8.       Log.e(getPackageName(),  
  9.         "Failed to create JSON object for Web view"); 
  10.    } 

WebView的缺點(diǎn)分析

和軟件開發(fā)的大多數(shù)情況一樣,我們必須審視WebView的一些缺點(diǎn),特別是在制作混合移動(dòng)應(yīng)用時(shí)要注意:

•     不是所有的Web view都渲染成同樣的效果 在過去的兩年中,Web view的功能有明顯提高。然而,你的用戶群可能不會(huì)運(yùn)行Android或iOS的最新和最優(yōu)秀的版本。 Android平臺(tái)在Web view方面已普遍落后于iOS。Google似乎在重新努力來改善這種情況,但那些停留在舊版本的Android(尤其是Ice Cream Sandwich 4.x版本前)的用戶可能會(huì)發(fā)現(xiàn)Web view的性能尤其是復(fù)雜的表格,其效果和在iOS上呈現(xiàn)的并不一樣。開發(fā)人員需要在Android 2.2,2.3和4.x上測試HTML5代碼以確保內(nèi)容呈現(xiàn)的一致。
•    性能問題
Web view的性能通常是比不上原生代碼。然而,在許多情況下,你可能會(huì)發(fā)現(xiàn)性能是完全可以接受的,特別是在當(dāng)前的硬件飛速發(fā)展的情況下。請記住,原生代碼和代碼Web view部分調(diào)用的銜接性能會(huì)有一定的影響。但一般來說,不會(huì)要求在毫秒級完成調(diào)用,對于大多數(shù)應(yīng)用,這是不是一個(gè)問題。
•    滾動(dòng)條問題

用戶可能無法區(qū)分Web view的滾動(dòng)條滾動(dòng)方式和應(yīng)用程序原生代碼滾動(dòng)方式的不同。這其中的一些問題可以通過在新版本的WebKit中使用CSS3的-webkit-overflow-scrolling:touch屬性去解決。你可能也想看看解決方案,如FTScroller 和 iScroll。
•    復(fù)雜性

正如前面提到的,如果將內(nèi)容從Web服務(wù)器中下載到移動(dòng)設(shè)備,必須確保擁有必要的基礎(chǔ)設(shè)施來支持。因?yàn)楝F(xiàn)在應(yīng)用程序既有原生代碼,也有Web服務(wù)器和潛在的后端服務(wù)參與,這會(huì)存在更多的故障點(diǎn)。你必須針對早期部署版本的應(yīng)用程序做好兼容性測試,以確保當(dāng)有應(yīng)用更新的時(shí)候,現(xiàn)有版本的應(yīng)用程序仍然運(yùn)行。
•    遵守開發(fā)者協(xié)議

開發(fā)者的你必須熟悉每一類移動(dòng)應(yīng)用商店對web方面內(nèi)容的限制。正如本文所提到的,特別是在iOS平臺(tái)上要額外注意,否則會(huì)不允許發(fā)布甚至下架。
•    安全性

如前所述對于所有來源于web的內(nèi)容都應(yīng)該持有懷疑的態(tài)度,尤其是如果將和你的本機(jī)原生代碼交互的。確保你只暴露你需要使用的原生代碼部分。如果不這樣做,可能會(huì)導(dǎo)致一些Web的惡意代碼能調(diào)用本機(jī)代碼。必須確保將Web的安全實(shí)踐考慮進(jìn)來以確保Web代碼的安全調(diào)用。

鑒于一個(gè)混合型移動(dòng)應(yīng)用所帶來的靈活性,如果你發(fā)現(xiàn)Web view的性能在交互方面不夠優(yōu)秀,則可以在應(yīng)用中編寫原生代碼。當(dāng)然,編寫更多的本機(jī)代碼,則在平臺(tái)遷移的時(shí)候需要更多的重新改寫,這是一種利弊權(quán)衡??偟膩碚f,混合型移動(dòng)應(yīng)用的解決方案能讓你最大限度掌控應(yīng)用的性能和靈活性。

小結(jié)
移動(dòng)應(yīng)用開發(fā)中使用HTML5目前是個(gè)有點(diǎn)爭議性的話題。然而,重要的是要作為開發(fā)者,必須了解每一種解決方案的優(yōu)缺點(diǎn),了解什么樣的策略是適合你的應(yīng)用程序,這些都是由需求決定的。盡管移動(dòng)HTML5的解決方案在最近幾個(gè)月已經(jīng)有一些負(fù)面的宣傳,但本文還是講解了使用HTML5的好處。
無論采用什么方法開發(fā)移動(dòng)應(yīng)用,必須保持性能的高效和安全性,并且盡早測試,采用多種設(shè)備測試。在這篇文章中,我們已經(jīng)看到,HTML5帶來了許多好處,特別是采用混合HTML 5和原生代碼開發(fā),則給開發(fā)者更高的自由度選擇。

責(zé)任編輯:張葉青 來源: 51CTO
相關(guān)推薦

2012-02-20 13:45:26

HTML5移動(dòng)開發(fā)程序

2011-08-29 17:27:47

HTML 5交互移動(dòng)應(yīng)用

2015-10-13 11:49:06

移動(dòng)·開發(fā)技術(shù)周刊

2014-03-18 09:20:17

HTML5移動(dòng)開發(fā)

2015-01-12 12:11:10

移動(dòng)應(yīng)用原生混合

2015-01-12 09:52:08

移動(dòng)應(yīng)用原生混合

2015-07-03 11:07:39

HTML5移動(dòng)Web

2015-10-23 13:44:14

巴巴獵

2011-12-28 15:32:46

HTML5移動(dòng)App

2011-08-10 13:44:22

HTML 5

2011-12-12 10:08:39

jQuery MobiHTML5

2011-12-08 11:01:45

HTML 5

2012-02-23 10:28:43

AppCanHTML5移動(dòng)應(yīng)用

2014-12-22 15:02:48

HTML5移動(dòng)應(yīng)用開發(fā)

2011-05-25 09:34:30

HTML5cssjavascript

2013-06-27 14:33:00

2014-10-21 17:34:11

HTML5移動(dòng)設(shè)計(jì)

2015-03-26 14:04:57

2017-06-27 13:34:33

移動(dòng)開發(fā)直播

2012-06-05 13:37:19

HTML5
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)