2012年5月26日 星期六

Titanium ios/android同專案開發心得

這篇算是一個階段性的總結
先說一下專案過程,這是一個LBS型態專案
其中使用了一些比較fancy的UI/UX
也使用到了一些分享功能(簡訊、email之類、fb)
一開始是從ios版本做起
之前有一個lite的iOS版本,也是用Titanium開發的

這次開發pro版本時
由於繼承了lite版本的不少程式碼(約一半)
基本上開發速度蠻快的
Titanium在某些方面是有它的優勢存在的
包括
可以使用JS語法處理:
無論是iOS或android,要搞懂他們的語法和架構多少都需要一些時間,甚至是不少時間
而Titan提供用JS語法進行開發的功能,這點對於許多了解JS語法的開發者而言,一定是一個利多
但是由於不是原生語法,如果專案中要用到一些比較底層的功能,就會很麻煩
如果是Titan沒有提供支援的功能,也會很麻煩

整合了一些常見/常用的元件和方法
Titan在網路傳輸這塊整合的不錯,此外還包括FB、資料庫的語法整合也很方便
不過這三個領域在andoird或ios上都有一些不錯的整合元件
真的要說的話,大概只有fb的整合算是比較獨特和省時間

一開始寫ios版本時
大部分的時間都花在調整UI/UX上面
好的UI/UX是一個app一定要有的元素
UI/UX也許不用很獨特、很絢麗
但至少要是一個讓使用者可以很快速了解、使用的介面設計

這部份加入前後的修改,和一些思考及功能上的調整,大約花費一個多月左右完成
這期間使用Titanium處理iOS時,有碰到一些問題,但沒有多少bug出現
比較特殊的大概是Titanium還不支援ios上的簡訊功能
所以有引用SMS模組,但是SMS模組在使用上有一些問題
由於之後設計變更,沒有繼續使用,所以現在不確定是因為SMS模組的問題
還是因為把SMS模組套用到scrollview中的按鈕上的問題
(這部份之後會提到,Titnaium中並非所有元件都能配合無誤,目前為止,很多元件放在scrollview中常會出現一些不可理解的行為,或稱為bug…

在決定使用同一套程式碼進行android開發時,才真正陷入bug地獄..
首先,我要說明一下,以下提到的情況未必都是titanium的問題
android的版本之多、硬體組成之複雜從來不是新聞
即使使用原生android程式碼,也很少有人能保證不會碰到問題
其中尤其以影音相關功能最為複雜
但是在Titanium上,影音相關的問題我這次碰到的情況並不多
最主要的大概只有使用相機拍攝照片並上傳時,會一次記錄兩張照片的功能而已..
喔,使用相片膠卷挑選照片上傳好像也會讓照片自我複製一次…

還是先從ios/andorid的基本元件設計開始談起好了..
iOS和andoird的基本畫面設計本身是不同的
最簡單的就是andorid沒有上方的navbar設計
這種設計當然是可以模擬出來的
但是對應的navigation group功能就不是簡單的模擬可以做到的了
這就是同一套程式碼要對應android和ios時要碰到的第一個問題
這問題會很煩,但不是無解
只是要多花費一些心力去處理畫面進出時的設計
不過由於有了本來的ti for ios程式碼,加入這設計時可能會讓程式看起來有一點雜亂

接下來我碰到的問題在於ios獨特的元件設計
例如toolbar, systembutton
android在這方面非常欠缺
最簡單的例子是刪除用的垃圾桶圖示
在titnaium中,可以使用iphone.systembutton.delete這樣的簡單語法提取iOS的垃圾桶圖示作為按鈕
(雖然只能放在toolbar或navbar上)
但是在android(2.2)中並沒有(Titanium官方只宣告支援2.2,其他的版本多少有相容性,但是個人建議別去踩那地雷..你之後還有很多地雷可以踩個夠..)
在android上少了這設計就表示你需要自己弄一個按鈕,自己標明"刪除鈕"
如果想要精美的垃圾桶圖示,請找美設人員討論..
平心而論,這不是大問題
就算是在iOS上,由於toolbar的限制,這種系統icon也不是隨時都可以使用的
而且這是ios/android 在基本架構上的不同,與titanium本身優劣並無干係
當一套app要在這兩個不同平台上開發時,這本來就是必須花的功夫之一
不過加入前面說的ti for ios程式碼後,會讓整個程式碼結構看起來更雜亂了一點
不過這部份和程式流程/UI結構關係並不大,其實還可以接受
修改起來也不是太麻煩
處理這部份問題時,我主要的工作都在於搜尋ios元件,然後替換成對應的android可使用元件

修改這部份後,原始專案終於可以在android平台上測試了
這時候android解析度不統一的問題就出來了
ios上由於有自動判斷解析度加入@2x而且長寬比不變的設計,在iphone 3gs/4/4s上只需要注意某些硬體元件是否存在就可以(雖然這三種機型的硬體元件只有規格差別而沒有是否存在的差異)
但是android上面的螢幕長寬比、解析度差異很大,在這部份就要特別小心
這部份我們所採用的是懶人作法:強制使用預設長寬比設計
主要是在tiapp.xml中加入一個簡單的設定

接下來才是正式的測試
首先碰到的是android平台在GPS定位上的速度比ios慢,慢很多..
所以需要修改原本的單線流程,改成使用callback方式,讓機器抓到GPS訊號後才執行對應程式碼
這部份ios可以通用(說實話這是比較好的作法)

但是接下來就是一堆地獄了..
說真的,現在想起來,我覺得titanium對於ios的支援程度好很多..
我並不真的確定原因..但是我覺得和ios的穩定性以及架構相對完整有很大關係
我們的專案由於有特地強調UI/UX,並加入一些作法減少使用者的等待時間
所以在物件架構上相對比較複雜,有2~4個物件常駐背景並等候呼叫和執行
這些物件在iOS上使用時,透過navigation group的push/pop方法就可以運用
但是在android上不行..在android上使用back或close時,物件就會被關閉
這問題的出現,一方面是因為我方原始的設計不夠成熟
但也不能忽略titanium在這方面的移植性設計不夠完善才導致這種令人騎虎難下的情況出現
由於時間壓力,這方面我們使用了簡單的show/hide方法繞過
使用這方法繞過的一個主要考量在於這些設計和程式行為有關
所以不再能像UI元件一樣使用簡單的if(iiOS them ooxx 方式來進行簡單的分支處理
可是這還沒結束…

titanium on android上,對於層層套疊的元件在編譯時很容易出問題
一個簡單的 xxx.hide指令
當xxx"直接"附屬於最底層的window時,是很正常的
但是當xxx放置在scollview,scrollview又放置在tablerow中時,hide指令就無效了..
在iOS上一開始也曾經出現類似問題,但是當時出現的問題主要在於效能方面(tableview先出現,一閃之後才會出現裡面的元件)
元件的基礎指令如hide 無效的問題並未被觀察到


另外,如同上上一段所說的,為了減少使用者等待時間,我們有一些物件是常駐背景處理的
因此無可避免的,我們有一些事件處理會呼叫這些背景物件執行,也會根據執行結果安排元件並顯示出來
但是在操作這些背景元件時,titanium對這些元件的處理方式有奇妙的不同
在iOS上,開啟一個window放置背景後,可以輕易的操控其中的元件屬性
並在操作完成後顯示window
但是在android上,這些元件未必是可操控的,這問題尤其容易發生在元件不直接附屬於window時
即使是在同一個active window中的元件,由於上一段所提及的因素,要操作其行為也未必可行
當元件是scroll開頭的scrollview或scrollableview時尤其明顯

另一個問題是,在android上,當在table row中加入一個圖片當按鈕
指定圖片點擊動作為開啟新的window,當window關閉時
android有可能出現z-order錯誤問題
這問題幾近無解
因為他牽涉到的是titanium編譯指令的方法和android的行為
唯一可信的解法是使用heavyweight方式開啟window,如 modal:true
不過這解法也並非100%完美..

整體而言,將這套在ios上完美的程式碼轉移到android平台時
只有和UI無關的傳值行為可以不用花心思處理
其他的諸如表格點擊之類動作都或多或少有一些相容性問題(ios上e.rowData可以用,android上可能就要測試e.source之類)

結論
如果將titanium定位在快速建立簡單的iphone app的話,titanium還蠻完美的
如果想用titanium開發簡單的android app,應該也不會碰到太大問題
但是想要用同一套程式碼同時覆蓋兩個平台的話,我會建議先行判斷你的app是否符合以下條件
畫面設計簡單:這方面說的不是功能上的簡單,而是UI架構上的簡單,建議最多不要超過二層
也就是頂多用到 base window/wrapper/ UI 這樣的設計就好
這條件並不表示你的畫面要維持素淨,只要在一層之內,你想加多少image其實都不是問題
如果可能的話,最好是只有一層如 window/lavel
程式架構簡單:盡量維持一次只有一個window,背景最好不要有其他元件
這條件可能會讓app在開啟新的畫面時多花費一些時間,但是可以有效的降低你處理背景物件時花費的時間。一些額外的好處則是可以節省app的記憶體空間
UX設計不要太複雜:一些動畫還是可以用的,但是別讓這些動畫擴及到active window以外的元件
盡量遵守MVC設計:程式歸程式,ui歸UI,資料歸資料,千萬別讓資料和ui卡在一起。
盡量使用callback:如果你不確定怎麼把app架構拆成MVC,起碼你可以使用callback方式來處理程式。當然兩者一起就更好了,這可以讓你的程式更好掌控和管理

最後一個問題,我會後悔學習Titanium或用它開發嗎?
我的回答是不會,Titanium在建立app上確實有它的優勢和特色,包括快速的學習曲線和快速的開發
但是它的應用範圍顯然沒有原生語言/IDE來的廣泛和深入(喔,Titanium沒有 xcode的interface builder之類拉畫面的附屬程式,不過反正android也沒有這種支援程式..應該沒有吧)
當然你可以自己建立Titanium module來擴展它的能力,不過走到那一步的話,你還能享受到多少快速/簡易特性?
titanium在原生UI元件的支援上未必100%支援(例如ios上的sms功能...)
不過一些簡單的元件如label, button之類,基本上都有支援

但是當ios上完美運作的程式卻在android上由於UI套疊後的存取/控制問題變成蟲族母巢後
我就開始後悔用它做這種開發了
記得,別給Titanium太大的發揮空間,能簡單就盡量簡單

補充幾點
Titanium的debug能力非常基本,除了簡單的語法錯誤和log方法之外,幾乎沒有其他debug作法
不過可以透過使用xcode/eclipse開啟編譯過專案的方式處理
和ios/android相比,Titanium api和開發資訊相對而言少很多
最後
Titanium用在iOS上比android穩定很多,如果只是用來顯示網頁資料的app,更是幾乎不會有任何問題

5 則留言:

Charlie Ueng 提到...

你好
想請問一下
我在scrollableview裡面放的imageview圖片常常消失
而且有時候翻頁翻回來出現之後
在翻過去一次之後圖片又不見了
不知道能怎麼解決:(

愛迪生。吳 提到...

我沒碰過這問題,感覺上這問題也不該發生
你這問題會讓我直接想到是環境問題
建議你可以說說你的環境 (你的機器、Ti版本、模擬環境)

基本上我對於 TI 在 android 上的表現很不信任
TI 在 android 2.2 以外的環境抱持懷疑
Ti 在 Android 2.x 以外的環境視為不可靠..
如果是模擬器的話,android 模擬器在 mac 基本上就是一個災難..買台二手 android 會讓你生活好過很多

Charlie Ueng 提到...

我是用兩隻手機測試
samsung galaxy ace,android 2.3.3
這隻沒問題
另一隻是
HTC one X, android 4.0
這隻就有出現問題
Ti的版本是2.1.1 GA

愛迪生。吳 提到...

Ti官方只支持到 2.2..
半年前資訊,不過應該變動不太大
詳細情況你可以去找找,一時找不太到
超過2.2, 差距越大,越有機會出現奇妙問題..

我只用過 galaxy tab 測試(2.3.x),相容性感覺不錯
4.0沒測試過,其實也沒打算想過支援 :p

android 不是我的主力,以下意見只是局外人想法
要支援 android 4.0的話,phone gap 可能會比較好一點點.. 雖然他在手機應用程式端(如相機)很不夠力
不然考慮原生 android 或找一下有沒有其他解決方法 (java 系出名的就是解法多、超多、無敵多
如果是我,應該會把Ti限定在 iOS裝置上或畫面非常簡單的 android app

Charlie Ueng 提到...

謝謝你的回應,我看了一下官方的網頁,上面寫好像是可以支援到4.0的樣子。
http://docs.appcelerator.com/titanium/2.0/index.html#!/guide/Titanium_Compatibility_Matrix

我用了DDMS測試之後,log出現了這行
08-22 15:45:31.190: E/TiDrawableReference(16546): (main) [310,25789] Unable to load bitmap. Not enough memory: (Heap Size=64867KB, Allocated=57346KB)
看來還是ti的問題...