淘宝彩票移动项目开发实践
轉自:http://ued.taobao.com/blog/2012/10/11/%E6%B7%98%E5%AE%9D%E5%BD%A9%E7%A5%A8%E7%A7%BB%E5%8A%A8%E9%A1%B9%E7%9B%AE%E5%BC%80%E5%8F%91%E5%AE%9E%E8%B7%B5/
作者按:如今越來越多的互聯網產品開始在移動終端發力,終端產品越來越豐富。但是,平臺差異帶來的開發成本浪費很讓人頭疼。一段時間以來,淘寶彩票前端組也在努力尋求移動終端項目開發最佳實踐,盡管諸多方面不甚成熟,但拋磚引玉,希望我們的總結整理會對大家有所啟發。
淘寶彩票客戶端產品目前有兩條體系:
2、嵌入式應用:作為子應用的軟件包形式提供,嵌入到第三方的客戶端軟件中,比如淘寶主站客戶端以及支付寶客戶端等
由于產品的共通性,這兩類應用都是需要考慮較多復用性和開發成本的。在原生App中,有不少內容是可以用簡單的HTML5來實現的,比如iPhone客戶端中的“訂單頁”:
而在子應用的軟件包里,則有更多的地方可以運用HTML5來實現,包括一些復雜的富交互。例如支付寶客戶端中各彩種的實現:
App的形式
目前移動終端上的應用主要以Native App為主,這種應用的優勢是:
2,可訪問本地資源,更有效的利用設備,節省流量;
3,并且已有一定規模(App Store),付費模式明朗。
缺點是:
2,所有發布需要經過App Store的審核。
當然,目前還存在一些Web App,用戶可以直接通過瀏覽器來訪問,例如Gmail。這類App的開發和維護的成本低,可以天然的在各種終端上執行,并且容易迭代更新,無需用戶進行安裝。不過就現階段而言,無論從速度上還是交互上,用戶體驗與Native App的差距還是比較大的。既然兩種App都各有利弊,那么我們就干脆將二者相結合:用原生控件做外殼和交互,保證流暢的用戶體驗和完整的推廣渠道;使用HTML5來展示內容,保證內容的迅速迭代更新,即時響應用戶需求。于是就誕生了Hybrid? App,這也是目前最流行最合適的一種App形式。
對于前端工程師而言,在移動平臺上沒有了IE系列的困擾,HTML5的很多特性都可以大膽的運用。不同的是,我們需要設置一些針對移動終端的Meta屬性,以及更合理的利用Media Query(主流移動設備的分辨率信息)。
JS框架的選擇
找到適合使用HTML5的場景,這時就需要考慮JS框架的選擇。首先需要明確的是,類似jQuery和YUI這種“重型”的庫,由于包含了很多處理兼容性方面的代碼,且API設計過于細致而顯得太過龐大,并不適合移動端。我們可以選取一些專業的用于Mobile開發的JS類庫,例如jQuery Mobile,Sencha Touch等。jQuery Mobile是目前最流行的一個移動開發的框架,文檔豐富,社區活躍,有很多的UI控件供我們使用,并且提供對多頁面的支持(通過Ajax方式讀取內容,并提供頁面切換的過渡動畫)。我認為jQuery Mobile的最強大之處就在于其UI方面的支持,但這一部分恰恰不是我所需要的。Sencha Touch是ExtJs的移動版,對于不熟悉ExtJs的人來說有一定的學習成本。
我們選擇了zepto.js作為底層庫,使用sea.js進行模塊的管理和發布,原因是基于CMD規范的模塊文件最終需要打包入應用的軟件包里, 或是打包后發布到線上;此外,我們使用backbone.js為基礎的MVC架構,用來剝離應用的數據部分;使用underscore.js做為前端模板引擎(backbone重度依賴);使用iScroll.js為我們提供模擬滾動的功能。這些都是一些專業的“小庫”,很適合移動端的開發。當然,具體情況需要具體分析,沒有萬能的框架,只有萬能的開發者。如果時間允許,也可以自己來定制一套滿足自身需求的基礎庫。畢竟在移動端,一切以 “精簡”為主。
應用架構的選擇
首先拋出兩個小問題:
2,? HTML5最大的優勢就是跨平臺,只需要開發一套代碼,就可以完全通用于不同的終端。但是,真的一套代碼就能“吃”盡所有移動終端么?
先解答第一個問題。其實我們在開始嘗試的時候,完全是參照PC端的OPOA來進行的,把很多的內容都放在一個Page里面,通過URL或Hash的方式來管理頁面的顯示。但實踐表明,在移動端這樣做是有很大弊端的。首先,在PC上顯示區域比較大,我們可以先給用戶展示一個框架,然后在分塊的去顯示內容,但是移動終端由于屏幕變小,往往同時只能展示一個區域,那么我們首先要根據URL判斷顯示哪個區域,然后再去加載這個區域的內容, 這樣一來,讓本來在移動端就變慢了許多的頁面更加的雪上加霜。其次,為了減少請求,我們通常會把大量的前端模板都塞到這個僅有的Page中,不僅導致頁面體積變大,性能降低,而且維護困難。因此,我認為,在移動端最好的方式還是傳統的多頁面開發。
那么肯定有人會問,這樣子的話豈不是會損失頁面切換的流暢性,讓用戶不爽么。這個問題我們是可以解決的。第一就是采用jQuery Mobile的方式(Web App中非常適用),切換時用Ajax去請求新的內容,然后再渲染到頁面中。這種方法在某些特定條件下會有問題:我們仍然需要使用URL來進行歷史的管理,如果將這些頁面作為靜態文件打包在客戶端中的話,在一些Android系統的手機中,硬件會將這些帶后綴的文件當成一個完整的文件去查找(例如 index.html?page=XXX),然后發生錯誤。第二個方法就是在Hybrid? App中,我們可以借助客戶端來幫助我們進行頁面的切換。你只需要告訴客戶端即將要跳轉的URL路徑(可以是網絡請求,也可以是本地靜態文件),然后由客戶端進行跳轉。這樣就可以在客戶端代碼里面設置Webview切換的動畫效果,使客戶端的整體風格更加的統一。
針對第二個問題,我們剛開始的目標就是用一套代碼來自適應所有的客戶端。結果發現,在iPhone和Android上,盡管風格差別較大,但是整體的結構和布局是很相似的,那么只需要設置兩份CSS文件,再提供一份API,分別在兩個平臺上做實現就可以了,維護起來很方便;但是在iPad 上,由于布局和交互變化比較大,為了復用,不得不在原代碼上增加分支,不但破環了原代碼的完整性,而且維護時會產生一些意想不到的錯誤。這樣就得不償失了。因此,如果手機客戶端和平板電腦客戶端差異很大的話,最好還是分開單獨進行處理,而不是為了“復用”而復用,大家可以根據具體的情況制定自己的策略。例如彩票的iPad客戶端,我們就是純粹基于HTML5為pad量身定做的:
Webview及其與HTML5的通信
Webview是手機中內置的一個基于webkit內核的SDK,是搭載Web頁面的容器,也是負責Web頁面和Native App之間相互通信的橋梁。在不同平臺上Webview的實現是有較大差異的。
在Android平臺中是支持JS方法和Java方法的直接調用的,我們通過下面的代碼即可實現互相調用。
//將JAVA對象綁定到JavaScript中mWebView.addJavascriptInterface(new JsToJava(), 'stub');//在JavaScript中調用Java方法window.stub(); function invokedByJava(data){//do something}//在Java中調用JavaScript方法public void onClick(View v) {mWebView.loadUrl("javascript:invokedByJava('java_data')");}//打開webview,調用頁面mWebView.loadUrl("file:///xxx.html");但在iOS平臺上,SDK沒有原生提供JavaScript調用Native代碼的API,只有反向調用的方法。要想在JavaScript中調用Native,一般有兩種方法:一種是Phonegap采用的iframe方法,也是比較推薦的,如下所示;另一種是直接修改頁面的location,在大部分情況是可用的,但是有時候會產生一些莫名其妙的錯誤。這兩種方法的原理都是相同的:利用Webview去截獲JS發起的特殊的網絡請求,然后對其進行處理。
//Objective-C - (BOOL)webView:(UIWebView *)webViewshouldStartLoadWithRequest:(NSURLRequest *)requestnavigationType:(UIWebViewNavigationType)navigationType {NSURL * url = [request URL];if ([[url scheme] isEqualToString:@"gap"]) {//在這里做js調用native的事情//...//完成之后回調js//[webView stringByEvaluatingJavaScriptFromString:@"alert('done')"];return NO;}return YES; }//通知iPhone UIWebView加載url對應的資源,url格式為: gap:something function loadURL(url) {var iFrame;iFrame = document.createElement('iframe');iFrame.setAttribute('src', url);iFrame.setAttribute('style', 'display:none;');iFrame.setAttribute('height', '0px');iFrame.setAttribute('width', '0px');iFrame.setAttribute('frameborder', '0');document.body.appendChild(iFrame);//發起請求后將其從DOM上移除iFrame.parentNode.removeChild(iFrame);iFrame = null; };除此之外,不同平臺的Webview還需要進行一些特殊的設置,才能讓其和原生的瀏覽器的行為表現相一致。例如:在Android Webview中,JavaScript和localStrorage都是默認禁止的,需要提前啟用;Android的物理后退鍵默認是會關閉當前的Webview的,而不是執行history.back();在iOS5.0以下的系統中,設置格式檢查的Meta屬性會偶爾失效,需要在 Webview中直接關閉其格式檢查等等。在D2沙龍的PPT中有詳細的描述,大家有感興趣的可以看下。
速度/性能
對于一個互聯網產品的用戶體驗來說,速度和性能幾乎是最重要的因素。但令人遺憾的是,這也是目前阻礙Web App發展的最大的障礙。原因主要有以下幾個方面:
1 低端設備多,受硬件的限制。根據木桶原理,一個木桶的水量是受最短的板的限制的。與之類似,我們在衡量頁面性能的時候,也需要看其在中低端機型上的表現,尤其是廣大的Android千元智能機。如果Android所有的機型都能有Samsung Galaxy的表現,我們也就不用愁眉苦臉了,但是在更多時候,我們不得不為了在HTC野火上能夠正常的展示而放棄在Samsung上看起來非常帥氣的效果。
2 簡化的瀏覽器實現。本來相比桌面版的瀏覽器,移動版的瀏覽器已經在功能上做了一些簡化,性能上有些差距。但是,與原生的移動瀏覽器相比,Webview會更慢。下圖為一個頁面分別在Mobile Safari和Facebook的iPhone客戶端中的運行結果,我們可以發現,UIWebView中的JS運行時間大概是Mobile Safari的3-4倍,這恐怕也是Facebook放棄HTML5轉向原生應用的一個原因之一。
針對上述原因,我們總結出一些性能優化的小Tip:
2 減少DOM數量,盡可能少的使用position:relative,減少對DOM的操作
3 用CSS動畫代替JS動畫,在Android平臺上可以平穩退化,放棄動畫效果(包括CSS3動畫)
4 避免GIF圖片的使用(消耗內存)
5 如果只是在移動端使用的話,請使用iScroll-lite來代替iScroll(iScroll里面增加了很多額外的功能,比如在PC上模擬滾動),在允許的情況下,可以關閉滾動條(滾動條也是創建的DOM元素)
關于滾動,還有一些其他的想法,大家有興趣可以一試:
2 用Canvas來代替Scroll,但是文字的渲染可能會有些問題。
由于篇幅原因,這里就不贅述更詳細的性能問題了~
移動終端的網絡環境
移動應用最大的特點就是方便、隨處可用。但無論是2G還是3G,我國目前的網絡狀況都難以滿足移動應用的要求。相比于Native App,Web App除了要下載數據和圖片外,還需要下載一些額外的js/css文件,這些動輒上百K的靜態文件對于平均速度還不到10K的2G網絡來說實在是太龐大了。 因此,目前最好的應用場景還是將頁面打包到客戶端中,版本變化時提醒用戶讓其主動進行更新。盡管這樣會損失一部分web頁面的靈活性。
調試
開發時的調試相對方便,可以基于瀏覽器進行。但開發環境和最終的執行環境還是有一些差異的,需要對終端的View中的“頁面”進行調試,現在我們的做法是 “打點”,即使用一個Log代理控件給代碼埋點,輸出log,以此來輔助我們的調試。目前常用的工具有Weinre和JSconsole等。這些工具的原理是比較類似的:通過網絡在其他機器上連接了一個調試的GUI,捕獲待調試網頁的JavaScript運行環境來查看代碼輸出或者對代碼求值,并可以監控和修改調試目標的DOM和CSS樣式。但是由于調試不是真正的發生在移動設備上,所以無法設置和捕捉斷點進行debug。
在最新的iOS6中,Safari(僅限Mac桌面版)中自帶了web檢查器工具,可以讓我們更方便的對iPhone/iPad上的Safari進行遠程調試。
更多內容可以點擊下載我在7月28日D2沙龍(北京場)的分享。
總結
以上是生活随笔為你收集整理的淘宝彩票移动项目开发实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 马建威android视频,5.25春季班
- 下一篇: 利用计算机画统计图.doc,信息技术应用