隨便搜索一下「Android vs. iOS」,都會出現不少關於哪一個平臺更好的爭論,大多數的爭論點都是關於市場佔有率、易用性和設備分化等問題。固然也有一些「以開發者的角度」去比較這兩個平臺的文章,可是不多有從技術上作深刻的比較,一般也只是用一個簡單的示例應用介紹一些基本的特性。缺乏這種深刻的比較實際上是有緣由的:一個公司要作一個足夠複雜的移動應用,一般須要一我的或團隊作Android,另一我的或團隊作iOS。這兩個平臺使用不一樣的編程語言(Java和Objective-C),提供不一樣的SDK,使用不一樣的開發工具,因此人力資源分配上各作各的平臺也就不奇怪了。html
GQueues是一個在線任務管理器,以前只有一個HTML5版本。最近我完成了GQueues for Android 和GQueues for iPhone & iPad 的開發。雖然這兩個應用的複雜程度不能和第一人稱射擊遊戲相提並論,但也毫不簡單 – 爲用戶存儲和管理數以千計的任務信息、支持多帳戶、提供到WEB端的後臺同步、複雜的過濾、排序和分組功能。經過此次的實踐,我但願透過獨特的視角,分析和比較爲這兩個平臺開發GQueues應用的過程。python
-- | Android App | iOS App |
---|---|---|
啓動日期 | Sept 21, 2012 | Mar 2, 2013 |
第一個可測的Beta版本 | Dec 22, 2012 | June 10, 2013 |
應用發佈日期 | Jan 31, 2013 | July 18, 2013 |
項目總耗時 | 4.25 months | 4.5 months |
Ramp Up Time | 1 week | 2 weeks |
開發耗時 | 870 hours (approx) | 960 hours (approx) |
Beta測試&Bugfix | 34 days | 38 days |
Beta測試人員人數 | 92 people | 48 people |
代碼行數 | 26,981 lines | 23,872 lines |
應用大小 | 1.1 MB | 3.5 MB |
視頻預覽 | GQueues for Android Video | GQueues for iOS Video |
下載 | Google Play | App Store |
我已經寫了12年的代碼,但這是我寫的第一個Android應用,也是我寫的第一個偏向數據處理的iOS應用(2010年我作過兩個iOS 3上的遊戲,但那兩個遊戲主要只涉及一些動畫和藍牙鏈接)。 我最後一次用Java是在研究生階段,而個人Objective-C 也僅限於那兩個遊戲。因此對於這兩個平臺,我基本上能夠算是從零開始。android
簡單講,只須要花一半學習iOS的時間來學習Android,我就能開始Android開發。對於Android,我花了一週時間用來看書、跟着一些教程作一些測試應用,這些測試應用包含了GQueues將會用到的一些核心功能。作完這些,我基本上算是打好了爲GQueues設計架構的基礎,同時也能夠開始爲這個項目寫代碼了。在接下來的一週我能夠很輕鬆自如地基於Android作開發,而再也不須要依賴某個資源去實現新特性了。ios
對於iOS,我一樣按照上面的流程,但我花了兩週時間作各類測試/實驗,才讓本身以爲能夠開始爲這個項目寫一些基礎代碼了。其中大部分的時間都花在研究CoreData各類複雜的API上面。搞清楚怎麼設置、怎麼在線程安全的前提下,爲每一個用戶集中管理PersistentStoreCoordinators和ManagedObjectContexts也花了些功夫,最重要的是要支持多帳戶(這個話題可能須要另外一篇博客來單獨講講)。爲 FetchedResultsControllers開發一個可擴展的架構花了更多時間,FetchedResultsControllers用於支持可被用戶查看以及操做的任務表單、隊列和分類。最後又過了兩週(總共花了一個月)本身才能比較輕鬆自如地基於iOS寫代碼。git
總的來講,Android的文檔(官方文檔、第三方教程、圖書、代碼示例、StackOverflow)質量都很是高。我從一些著名的開源Android應用中學到了不少架構上的最佳實踐,如Google開放給開發者的2012 Google I/O app。此外,Android自己就是開源的,必要時我能夠本身查看Android的平臺代碼,弄清楚一些疑難問題。雖然iOS也有不少文檔,但因爲iOS5和iOS6相比以前的版本改動很是大,大部分文檔都已通過時,其中包括ARC入門一文(introduction of Automatic Reference Counting)。所以,大部分的示例代碼(包括Apple官方示例)和一些問題的解決方法都是不正確的,須要使用新的方法取而代之。搞清楚這些確定也須要花更多的時間。github
從上面的統計表中也能夠看出,開發GQueues for Android要比開發 iOS 版的快十分之一的時間,儘管在開發Android版的期間我從新實現了以前用於支持GQueues HTML5版的整個後端服務器同步代碼。而開發一個不採用原始iOS6風格UI的應用也須要多花些時間,單單比較這個數據,Android開發就是比iOS開發快。web
Android 應用正則表達式
iOS 應用sql
上面列出來的書其實用處頗有限,由於跟大部分的技術類書籍同樣,書的內容都有點過期了,並且大部分書只停留在入門級別的概念介紹。不過,在一開始的前幾天看一下這些書,可以比較快地理解平臺上的一些核心功能。就目前來說,對於這兩個平臺,在線資源仍然是最有價值的。數據庫
接下來我只簡單說一下這兩個平臺的開發工具,由於關於這個話題已經有不少的討論。我不是Eclipse或者XCode的腦殘粉,它們有各自的強項和弱點(其實我最喜歡的仍是Vim)。Eclipse的搜索暴慢並且很繁瑣。XCode Organizer的文檔搜索也卡爆了。Eclipse中使用log tags(經過Android插件的logcat集成)過濾日誌超級實用。兩個IDE的代碼補全都很不錯,XCode的Interface Builder一點用處都沒有(後面細講)。不過XCode Instruments就很是有用了,能夠用它作優化分析、調試等等。我開始作GQueues for Android的時候,Google還沒發佈Android Studio,不過在GQueues的後續更新版本中我會拿它來試試。
若是你一邊寫代碼一邊測試,用Android的模擬器簡直就是浪費時間(真不敢相信它能慢成這個鳥樣)。在開發過程當中,我都是直接部署到真機上測試的,用真機快不少。iOS的模擬器則很不一樣,跟Android相比簡直就是火箭跟蝸牛賽跑,這也讓整個開發過程更加高效。每寫一小段代碼我都會在模擬器上跑一下,等到整個功能完成了我就會部署到真機上玩玩。
對於Android,我有各個版本的測試機器(除了Gingerbread,即Android 2.3),除此以外,就要倚靠beta測試過程當中各類設備的覆蓋了。對於iOS來說就要簡單不少了,我只須要拿GQueues須要支持的最舊的和最新的機器來測試就夠了。
Android App
iOS App
GQueues的其中一個需求就是必須同時支持任意尺寸的手機和平板,而且針對不一樣的表單元素進行優化佈局。因爲各類各樣的設備都運行着Android系統,Android也理所固然地有着成熟的UI組件幫助開發者支持各類尺寸。例如從Android第一個版本開始,RelativeLayout提供了View之間相對佈局的支持,可用於建立靈活、響應迅速的佈局。另外,在Android中全部的佈局都由XML定義,這設計界面的方式很是簡潔、簡單而且高效,試過iOS中建立佈局以後這種體會就更加深入了。
相對於Android的RelativeLayout,iOS有Auto Layout,這種佈局方式比較新(iOS 6新引入的),集成到了Interface Builder(IB)中,可是太難用了。我花了好多天學習IB中怎麼用Auto Layout,跟任何iOS 6開發者同樣,僅靠IB爲視圖(View)設定各類精確的約束,徹底改變了我本身的標準,這是由於IB所謂的「智能」系統時刻維持(糾正)着視圖佈局相對位置。我學了不少技巧,想着彌補IB的短板,可是沒啥做用。最後我只能放棄IB,轉而用冗長的代碼實現全部佈局。若是你放棄IB和富有極客範的ASCII art style來寫佈局,使用Auto Layout來實現仍是很強大、很直接的。但願蘋果在iOS 7中已經改善這些,不過我還木有試過。
若是一個應用須要同時針對小屏設備和大屏設備進行優化,最關鍵的就是基於屏幕的真實尺寸進行動態組合視圖,這種方式被稱做「適配性佈局(Adaptive Layout)」,平板電腦能夠在一屏中顯示兩個或三個視圖,而手機上一屏則只顯示一個視圖。Android經過Fragments支持這種設計,Fragment是一個獨立的、自包含的的模塊,可以在須要的時候直接丟到Activity中去用。經過使用Fragments,只須要調整幾行XML代碼就可讓GQueues的佈局適配不一樣分辨率的屏幕。對於我來說,Fragments是一種很是天然的解決方案,由於它是基於面向對象裏面兩個衆所周知的準則設計的 - 高內聚和低耦合。
經過Custom Container View Controller(你也能夠用Master-Detail模板,固然這種方式寬度是固定的,也不支持個性化定製),iOS支持一屏使用多個ViewController。對於這個不成熟的特性,我以爲Apple的文檔顯得很複雜和不完整,最好的資源還要數Ray’s iOS5 tutorials和WWDC視頻。我花了比預計要多的時間,終於搞好了在iPad上同時顯示多個View、在iPhone上顯示單個View的佈局架構。
簡單說,在Android上支持設備翻轉須要作不少工做,這些工做也是最終致使不少bug的源頭,而在iOS上,支持屏幕翻轉只須要作一點點工做,剩下就是系統幫咱們搞定了。在Android上,屏幕翻轉會直接銷燬現有整個視圖棧(Activity棧),屏幕翻轉完成後再重建每一個視圖。因此在GQueues中支持屏幕翻轉,我須要無時無刻保存好全部當前狀態,隨時保證翻轉後能正常恢復狀態。而在iOS上,系統會幫你管理全部屏幕翻轉相關的細節,惟一須要我關心的就是翻轉以後,我須要調整那些沒有被Auto Layout處理好的視圖的位置。
網頁開發上有一些常見的佈局在GQueues上實現起來很是困難,無論是Android仍是iOS。其中一個例子是在任務詳細界面顯示標籤。每一個標籤都是變長的,在必要時標籤須要自動換行。在網頁上實現這個只須要設置CSS的float值就能夠了。但無論是Android仍是iOS對這種「流式佈局」(Flow Layout)都沒有原生的支持,這也意味着我須要寫不少代碼本身去計算和擺放這些標籤,以達到「流式佈局」的效果。最後Android的代碼是基於Romain Guy的演講內容和 Artem Votincev 的flow layout實現的。在iOS上也採用了相似的方法,基於容器的總寬度,計算每一個標籤的寬度,最後設置auto layout的參數。對於這個佈局的實如今兩個平臺上都耗了很大的工做量。
關於Android的生態系統常被人吐槽的就是嚴重的系統分化。運營商推送更新的步伐老是很慢,因此如今仍有大量運行着舊系統的設備,這也就意味着若是要保證應用足夠大的設備覆蓋率,開發者就不能使用新版系統帶來的新特性。不過好在如今針對這個問題,Android社區作了很大的努力,提供了一些用於在舊系統上支持新特性的庫。經過使用Android官方的 Support Library和Jake Wharton的ActionBarSherlock Library,我幾乎能夠在Android 2.2上使用Jelly Bean(4.2)中全部的新特性。
對於iOS來講,支持舊系統一說幾乎不存在,或者說根本就不是關鍵。在準備階段我花了一些時間考慮從哪一個iOS版本開始支持,而當時的統計數據顯示使用iOS 6系統的設備已經達到 83%,而當時對於放棄支持iPad一代我也有一些疑慮,由於我老爸老媽老姐用的就是iPad一代,他們將是GQueues的鐵桿支持者。最後我決定仍是隻支持iOS 6+,這樣我能夠放開手使用Auto Layout,而不須要浪費大量時間實現任何過期的佈局技術。固然,我解決了iPad一代的問題(至少對我家裏人說來講已經解決),就是換掉他們的iPad一代,給他們每人買一個iPad四代(做者有錢銀)。
對於GQueues來講,數據是核心 - 把數據保存到設備上而後同步到WEB端。Android和iOS有着徹底不一樣的數據管理系統。Android提供了ContentProvider,它是SQLite數據庫上層的一個可被繼承的應用接口,做爲一個結構化框架被用於全部應用的數據處理。ContentProvider學習起來比較難,搞定一個GQueues可用的實現,前期須要花不少工做。一旦搞定了第一步後面的擴展和個性化定製都變得簡單多了。
一些背景信息,GQueues的web service是基於 Google App Engine’s Datastore 的,這是一個高擴展性的分佈式NoSQL存儲系統,而SQLite則是一個標準的關係型數據庫,擴展性明顯也比較差,但這徹底不須要考慮,由於這個應用只存儲一個用戶的數據。(順便說一下,架構上我採用了「一個用戶對應一個數據庫」的設計,這對於快速簡單地實現多用戶切換有重要意義,不過實現細節可能得再開一博來聊了)。無論怎麼說,Android的一個很大的優勢就是能夠建立 SQLite Views來支持Smart Queues。爲了支持 Smart Queues,搞清楚各類複雜的表關聯查詢和子查詢也花了寫功夫,可是這也讓Smart Queues的加載更加高效和快速,由於過濾不是在代碼裏面實現的(在SQL裏面)。
在iOS上,我用的是 Core Data,它是iOS上的「schema驅動數據圖形管理和持久化框架」,基本上它能夠被看作是一個NoSQL存儲,不過有趣的是,Core Data背後其實是SQLite數據庫(呃…實際上SQLite也是幾個可選項中最合理的選擇)。iOS也容許用戶直接建立SQLite數據庫,但只支持經過純C代碼來操做,對於其餘iOS組件沒有原生集成。Core Data的學習起來也比較困難,但最後我仍是選擇Core Data而不用SQLite,由於這樣我能夠輕鬆實現不少功能,包括緩存、數據模型遷移支持,還有經過 NSFetchedResultsController,能夠很是簡單地爲界面中的table(列表)提供數據。
管理數據集的關鍵就是使用事務,尤爲重要是作數據同步的時候 - ACID,即:atomic(原子性)、consistent(一致性)、isolated(隔離性)、durable(持久性)。Android上實現事務似很直觀,跟大部分關係型數據庫管理系統的實現方式是同樣的,所以,保證數據完整性並不困難。另外,用好SQLite中的UNIQUE ON CONFLICT REPLACE語句,在數據同步的過程當中建表、對記錄進行原子更新的時候幾乎不須要作任何額外工做。
嚴格來說,Core Data並不徹底支持事務。經過使用單獨的子ManagedObjectContexts作後臺線程處理,再加上@synchronized,可以處理好數據更新和同步,同時避免不正確的寫操做覆蓋(overwrite)。關於高效更新和建立對象,iOS給的建議幫助很小,總的來講,CoreData給個人趕腳很笨重,並無它聲稱的那麼好用。另外,在Android上,SQLite能夠輕鬆實現快速加載Smart Queues,而在iOS上,全部的過濾都必須在代碼中實現,就算用了大量的緩存,速度仍然很慢。
在GQueues for Android上增長強大的全文搜索功能很簡單,我模仿Google I/O應用裏面的搜索實現,使用了SQLite的 FTS3 特性。首先建立一個虛擬表,而後在一個存儲了用戶任務的表上設置幾個觸發器,由這些觸發器填充數據到虛擬表。作完了這些,剩下的就是設計一個搜索界面和爲搜索歷史添加存儲。
iOS的Core Data對於全文搜索並無原生支持,因此我經過在謂詞(Predicate)中使用LIKE語句,實現基本的任務描述和日記的搜索功能。這個實現固然沒有全文搜索那麼強大,但我認爲它已經可以覆蓋現實生活中大部分的使用場景了。
用於比較,我只會列舉在GQueues中使用到的幾個API。
正則表達式在實現GQueues中 Quick Add解析的時候扮演着一個很是重要的角色,幸運的是,Android和iOS對於正則表達式都有着原生的支持。Android中的Pattern和Matcher從第一個版本起就開始支持,同時也包含了不少正則語法,其中包括前向斷言(look-ahead assertion)和後向斷言(look-behind assertion)。iOS則從iOS 4開始引入NSRegularExpression類,使人高興的是,我能夠把我在Android上辛辛苦苦寫好的正則表達式幾乎原封不動地搬到了iOS上。
在設計界面的時候,我但願用戶在查看任務詳細的時候左右滑動切換。在Android上我用了 ViewPager和新的FragmentStatePagerAdapter類,FragmentStatePagerAdapter還處於試驗階段,而且只能經過支持庫(Support Library)來使用。我花了幾天的時間實現了一個綁定好數據的初級版本,同時解決了幾個關於重複菜單項的bug和在數據發生變化後的處理。這些比我預想的要困難不少,要不是由於左右滑動切換任務的用戶體驗那麼好的話,我真不想實現這個功能。iOS上的UIPageViewController就簡單不少了,雖然也有一些奇怪問題要解決,而且須要本身再加上緩存支持使滑動複雜視圖的時候達到可用狀態。
Android提供了了一個先進但很容易使用的speech-to-text API,只用20行代碼,我就把RecognizerIntent集成到GQueues,提供了一個自定義的語音輸入功能。但很遺憾,iOS並無提供支撐SIRI背後技術的API,開發者只能使用第三方庫,依賴鍵盤上的麥克風提供語音輸入的支持。我找了各類第三方庫,包括Nuance - SIRI語音識別的提供商,但發現沒有免費版本,收費版本價格不菲。因此最後GQueues只能靠用戶本身使用鍵盤上內置的麥克風選項來進行語音輸入,其實這也已經足夠了,只要用戶還記得有這麼個功能。
經過使用Intent,在Android上能夠很容易就能夠把個人應用集成到安裝在用戶手機上的其餘應用。一樣地,只須要不多的代碼,經過支持ACTION_SEND intent,我就可以讓用戶在其餘應用中建立GQueues任務。Android同時也提供了一個小部件平臺,因而我也作了幾個小部件,之後還會增長一些。iOS對於跨應用集成和桌面小部件的支持度爲零,徹底不支持這兩個功能。
在上面的統計概況表中已經指出,beta版面向真實用戶測試了一個多月。兩組測試人員都很是棒,幫我找到了數十計的bug,提出了增長一些特性的建議,對一些UI上不合理的地方提出了反饋。我經過私有的Google Group組織beta測試,這樣的beta測試保證了最後發佈的應用對人們是真正有用的。在每次beta測試的最後,經過調查問卷我收集到了不少有建設性的反饋,也幫助進一步判斷個人應用是否達到了可發佈的狀態。
讓測試者開始測試只須要發個APK的連接,讓他們下載到他們機器上(呃..他們還須要在設置界面中開啓「容許安裝Google Play之外的應用」的選項)。Google很方便地支持用真實用戶來進行alpha和beta測試,可在開發者控制檯和階段推廣中進行設置。在將來的版本更新中我想用用這兩個功能。
iOS中的beta測試困可貴多,就算用了 TestFlight服務,雖然TestFlight很大程度地簡化了流程。爲了知足Apple的控制慾,每部測試設備的UUID都要加到用於簽名beta版應用的證書當中。所以,每次要添加beta測試者的時候,不管是添加一我的仍是一羣人,我都須要從新build一遍個人app。除此以外,Apple還限制了你一年最多隻能註冊100個測試設備。因此我要當心利用好這100個坑,這也是爲何GQueues的iOS測試者只有Android的一半。
固然,不談談發佈流程,Android和iOS的比較都不算完,在Google Play上發佈GQueues是一件很好玩的事情,只要我認爲已經準備好了,我隨時能夠發佈個人應用。點下按鈕以後,30分鐘內,個人應用就能在Google Play上被全世界的用戶找到並安裝到他們的設備上。而在App Store上發佈一款應用,相信每一個iOS開發者都有一樣的感覺,那是一個使人感到鬱悶的經歷。通過了數月緊張嚴密的編碼,我只能把個人創做提交給Apple,而後等7天,7天以後審覈人員花2分鐘看看個人應用,最後拒絕了個人提交。我只能按要求作了修改以後再次提交,我又得等8天才在最後經過了審覈。固然還有不少關於提交應用到App Store的恐怖故事,跟他們比起來,我就像是公園裏逛了一圈。儘管如此,在本身的商業控制上要對這樣一個「情緒化的第三方平臺」作出那麼多的讓步,仍然讓我以爲很不爽。
從上面的分析來看,作GQueues的過程當中,並無出現平臺A完勝平臺B的狀況。Android和iOS在某些領域各有千秋,也都有須要改進的地方。從這兩個平臺的歷史來看,貌似目前Android勢頭更猛一些,不止體如今市場佔有率上,而是看到了Android近兩年在UI上的改進和開發平臺的穩步提高。而Apple則是封閉的王者,我也堅信他們在很努力地作着他們認爲是下一代移動計算革命的事情。無論怎麼說,當我想一想這6年間所興起的app生態圈,我爲本身在這個移動技術快速更新的時代,能在這兩個平臺上作開發感到榮幸。
原文:Android vs. iOS: Comparing the Development Process of the GQueues Mobile Apps
轉載自:伯樂在線 - neevek