Android 的屏幕滾動操作不如 iPhone 流暢順滑,是什麼原因導致的?

如題,比如刷微博時上下滾屏明顯不如iPhone跟手(即便是13,14年的旗艦機,拖動起來也沒有10年的iPhone4跟手),這是安卓系統底層跟iOS的差距,還是說安卓手機的屏幕反應速度都不如iPhone的?


幾個高票答案說的都是現象而非原因。
對 @劉長曦 專欄提到的 g+ 討論做了個摘要,出處在此
https://plus.google.com/105051985738280261832/posts/2FXDCz8x93s

首先,安卓不缺硬體加速的支持。從安卓 1.0 開始,安卓就支持硬體加速。菜單的顯示/隱藏、提醒的滑動漸變、Activity 之間的過渡以及對話框的顯示/隱藏等都是經過硬體加速的。

但硬體加速與安卓「窗口」的概念有關。比如以下這張截圖,就包含四個窗口:


狀態欄窗口 / 壁紙窗口 / 壁紙上的啟動器窗口 / 菜單窗口

安卓一開始的設計目標是「提供開放的應用平台」,在這種設計思路下,安卓通過許多個獨立的 UI 元素來分享屏幕:比如輸入法窗口和應用窗口就是兩個不同的窗口。而同一個安卓應用,也由許多 Activity 組成(比如聯繫人列表是一個 Activity,聯繫人詳情是另一個 Activity),每個 Activity 又有自己的窗口。發現了嗎?安卓 UI 一切皆窗口:從主屏打開聯繫人應用,你看到的是主屏窗口和聯繫人列表窗口的動畫;按下聯繫人查看詳情,是聯繫人列表窗口和聯繫人詳情窗口的動畫;顯示輸入法,是鍵盤窗口的動畫...早期的安卓使用軟體來渲染窗口內的內容:在 2.3 前,窗口內容由軟體渲染,而窗口的組合 / 移動則通過硬體加速繪製。

安卓 3.0 起,改進了對硬體加速的支持,可以用硬體加速繪製一些窗口內的內容,(感謝 @方振宇 指正,還是有些繪圖的API沒有完全用硬體加速實現,需要開發者手動選擇渲染方式。老應用跑在新版系統上強制開啟硬體加速有可能出現異常,就是因為系統的某些繪圖 API 沒有完全實現硬體加速,而強制使用可能就會出現問題。)隨著安卓版本更新,窗口內容對硬體加速的支持一直在改進,可以參考這裡 Hardware Acceleration。

但為什麼即便支持了硬體加速,也不能完全保證流暢度呢?事實上,安卓的這個多窗口設計,意味著 GPU 需要同時支持不同進程的多個活動 GL 上下文。而即便到現在,多數移動 GPU 執行上下文切換的代價還是相當高的。

雖然安卓有堆硬體這一說,但硬體加速的資源也很容易被安卓的渲染機制吃光。比方說,Tegra 2 足夠在 60 幀下把 1280*800 屏幕的每個像素點渲染 2.5 次。但安卓 3.0 中,光是打開「所有應用」的視圖,就需要繪製許多不同的窗口:需要對所有像素繪製一次背景;(往少了說)需要對一半的像素繪製一次 shortcut 和 widget 層;需要對一半的像素繪製一次圖標和標籤;也需要對所有像素繪製一次「所有應用」視圖的黑色背景,還有「所有應用」視圖的圖標和標籤...還不算對這些窗口做最後的組合,就把 GPU 的資源吃光了。當然,安卓對這個機制也有優化,比如把壁紙做成一個比屏幕大的窗口,這樣在主屏滾屏時就不需要重繪,只要移動窗口就行。而這個繪製好了的窗口,就不需要額外的 GPU 計算量了。

另一方面,OpenGL 硬體加速繪圖也不是萬能的,Nexus S 和 Galaxy Nexus 中,每個 OpenGL 應用會佔用 8MB 內存。要知道 2MB 的進程開支都是個不小的代價。這 8MB 內存可能從後台進程那裡分配而來,造成應用切換速度的下降。

為了提升流暢度,還需要許多其他方面的努力:安卓 1.6 對前後台進程調度的優化、2.3 中對輸入系統的重寫、 加入並發的垃圾收集等。舉一個流暢度不由硬體加速決定的例子:對滾屏操作,Nexus S 在 ICS 上的流暢度比在 2.3 中要低。這其實是因為計時機制發生了變化,有時在 ICS 中,當應用接收觸摸事件並繪圖時,可能在尚未準備好的情況下就獲得了下一個事件,從而導致跟蹤手指移動時可能錯過一幀,但這時幀率仍然是 60fps (這個 bug 已經修復了)。

@Julius 提到的是關於瀏覽器的渲染情況。在這方面,安卓和 iOS 的主要差別並非來自硬體加速繪圖。早期安卓在渲染網頁時做了與 iOS 不同的折衷:將網頁以序列方式連續顯示,而非貼片方式這樣在滾屏和縮放時不會出現 Safari 那樣的佔位符,但渲染的幀率不夠快。安卓 3.0 後改用了貼片方式,改善了滾屏和縮放的體驗。但不論是安卓還是 iOS,貼片都是由 CPU 渲染的。

還有,「安卓後台應用太多吃資源」的說法也有問題。安卓的 UI 線程以默認優先順序運行,後台線程以後台優先順序運行。切換到後台的應用強制以後台優先順序運行。而後台優先順序利用了 Linux 的 cgroup 機制,它將所有的後台線程放進一個特別的調度組中,它們滿打滿算也無法佔用超過 10% 的 CPU 資源

「安卓的觸摸事件不像 iOS 那樣優先」的說法也是錯的。你可以架梯子看看安卓進程的優先順序設定
http://developer.android.com/reference/android/os/Process.html#THREAD_PRIORITY_AUDIO

總的來說,根據 Dianne 的說法,多窗口設計對屏幕繪製的開銷,是影響安卓的流暢度的已知因素之一。但決定「流暢」的因素還有很多,抓住某個特定技術細節不放的說法都是有失偏頗的。

以上。


目前絕大多數主流Android手機性能都是過硬的,以Nexus 5為例,刷了Android L以後在Art環境和硬體加速的雙重作用下,Google+列表也是極為跟手的,但對比iOS上相同應用,你或許還是會覺得iOS更為流暢。
我認為主要原因是列表滾動的演算法的差異,滑動流暢是一種視覺上的感覺,受到阻尼,動畫曲線等各方面影響,並不是幀率能說明問題的(現在還寫不出60幀列表的程序員該打板子好嗎),Android scroller演算法雖然一直在優化,但就目前的效果來看也就是剛好能work並不能實現非常自然的滾動效果,舉個栗子:當你以極快的速度滾動列表時,在Android上列表會加速到一個超出預期的滾動速度,視覺上會覺得非常生硬,而iOS列表會保持一個合理的滾動速度,每一幀都如絲般順滑。


2014年9月9日更新:
上次主要針對題主說的具體問題「刷微博在蘋果和Android手機上的差異」在具體的設備上做實驗後進行了分析。
今天我對「Android的流暢性」做個更進一步的討論。加在後面。

===============================================================

我來說下我所知道的事情。我不知道iOS為什麼流暢,但我知道一些Android為什麼不流暢的原因。

首先,就題主所說的問題,我用iPad和小米Pad對比了一下微博滑動滾屏這件事情(2014年8月10日目前微博app最新版本,打開的是「首頁」和「發現」欄)。正如題主所說,直觀感受上明顯感覺iOS要流暢、舒服。

在這件事情上我認為主要是這三個原因:

  1. 速度曲線。
    當你滑動界面然後鬆手,這時界面會繼續滑動,然後速度減小,直到速度為0時停止。iOS下速度減小的這個過程比較慢,尤其是快要停的時候是慢慢停的,視覺上有種很順滑的感覺;Android下則從鬆手到停要快很多,相比之下有種戛然而止的感覺。
    從數據/技術角度來看這個事情,我們滑動界面的最終目的不是為了「動」,而是為了「停」,因此只要平滑的到達目的地,似乎越快完成這個過程越好,所以Android的選擇是理所當然的。但事實是,大家普遍更喜歡iOS的方式,這樣做顯得更順滑、更優雅。
  2. 幀率。
    絕大部分時間兩者都能保持60FPS左右的滿幀率。但都會有偶爾的掉幀。並且Android上要比iOS上嚴重很多。(好吧,比起前兩年,已經好太多了。)我前前後後滑動了幾十次,iOS在前面遇到1次掉幀,後面就很穩定了。而Android幾乎每滑動一次都會伴隨一次掉幀。這完全就是真真實實的卡頓,用戶必然會感覺到那一刻的不流暢。Android掉幀的原因我後面再詳細分析。
  3. 觸摸響應速度。
    從手指碰到觸摸屏,到屏幕上顯示處理這次觸摸產生的畫面,是需要時間的。時間越短感覺越跟手。據說iOS的觸摸屏的處理時間要比一般的Android手機快,這不是我的專長,不知道怎麼驗證。但在軟體系統層面,Android的顯示機制是app--&>SurfaceFlinger--&>Display,這比傳統的app--&>Display多了一步,主要基於這個原因,畫面最終輸出到屏幕要比傳統的方式慢一幀(16.7ms)。

我覺得第1點造成的影響最大,恰恰卻是最技術/設備無關的。如果微博app或者Android系統要改變,很容易就可以調得跟iOS一模一樣。但正是由於這是產品形態上的差別而不是純粹技術上的優劣,反倒成了Android最不太可能改變的。

第2點的影響其次,當然是指在目前這個大部分時候都能滿幀的情況下。這方面是Android從早期到現在進步最明顯的方面,使用了很多方法來優化幀率。但就算現在Android進化了很多,硬體性能也進化了很多,卻仍舊不可能徹底消滅掉幀的情況。

第3點通俗的講就是跟手性,跟手性的重要性不言而喻,但現在的差別比較細微,且具體數據我也不清楚。
我想過一個辦法讓桌面、微博這種內容和手一起動的應用繪製到屏幕的速度快一幀(16.7ms),其實就是抵消之前提到的慢的那一幀,需要framework層和app層一起配合改動,目前已申請了專利但代碼還沒進,將來有時間了應該會進到MIUI。感興趣的可以看看專利:滑動操作響應方法、裝置及終端設備。

===============================================================

最後我來用專業技術分析一下微博app在Android里掉幀的原因。非編程人員可以跳過。(這個過程我使用的是小米3高通版+最新版微博app。)

最初,我認為這種現象很像GC(垃圾回收)導致的,於是打開logcat觀察每次卡頓的時候有沒有GC發生。結果發現並沒有。停下來的時候才會有GC,這說明微博app在滑動過程中控制得不錯,在停下來的一刻才去分配內存,使GC不影響幀率。

然後我打開「開發者選項」-&>「GPU呈現模式分析」-&>「在屏幕上顯示為條形圖」(好像是4.4才有這個選項,之前的只能在dumpsys里看),這會在屏幕上直觀的顯示每幀繪製花費的時間。屏幕上有條基準線大概是16ms,如果超過這條線則很有可能掉幀了。如果下面的藍色部分很長則說明是軟體draw的部分太費時,那麼可以通過traceview來繼續分析draw的java代碼。(我假定了現在的app都是硬體加速的方式。)如果中間紅色部分很長則說明是OpenGL ES繪製過程太費時。可以用gltrace來分析OpenGL ES的調用過程。
打開選項後使用微博app,發現雖然偶爾有超基準線,但並不嚴重,並且卡頓的時候並沒有明顯異常。

於是我開始使用systrace,這下就很明顯了:

可以發現每隔幾幀,就會有一次大間隙,圖中我圈了紅圈圈的兩個地方都明顯超過正常的耗時時間。現在問題是,這些地方的代碼在幹什麼呢?是什麼花費了這麼長時間?

可以發現每隔幾幀,就會有一次大間隙,圖中我圈了紅圈圈的兩個地方都明顯超過正常的耗時時間。現在問題是,這些地方的代碼在幹什麼呢?是什麼花費了這麼長時間?

放大後發現都是這兩個:obtainView和setupListItem。它們都是在draw之前調用的,這也解釋了通過上一步的方法(「GPU呈現模式分析」)為什麼沒有顯示出來,因為那個方法只展示draw裡面的時間消耗。

放大後發現都是這兩個:obtainView和setupListItem。它們都是在draw之前調用的,這也解釋了通過上一步的方法(「GPU呈現模式分析」)為什麼沒有顯示出來,因為那個方法只展示draw裡面的時間消耗。
通過在源碼里搜索obtainView和setupListItem,可以發現是AbsListView的obtainView方法和ListView的setupChild方法打下的這個log。

接下來,我們用traceview來看看這兩個方法裡面究竟調用了什麼代碼導致耗時過長。
跟蹤obtainView最終到了這裡:

代碼混淆了,看不太出來了,也懶得再跟下去了。但隨便點了點然後看到:

代碼混淆了,看不太出來了,也懶得再跟下去了。但隨便點了點然後看到:

TextView.setText用了挺多的時間。感覺Android團隊應該優化優化這個方法。

TextView.setText用了挺多的時間。感覺Android團隊應該優化優化這個方法。
然後再來跟蹤setupChild方法:

都是measure佔用的時間,並且調用次數比較多。這應該說明了View的數量不少。用hierarchyviewer看了下,的確不少,一條微博有50多個View:

都是measure佔用的時間,並且調用次數比較多。這應該說明了View的數量不少。用hierarchyviewer看了下,的確不少,一條微博有50多個View:


結論:我們最終大致找到了耗時的代碼及部分原因。這兩個耗時方法應該都是有可能減下來的,但應該不那麼容易。

===============================================================

具體問題分析完了,這裡講講整體Android的流暢問題。

先聊聊目前最高票數的答案 邑封:Android 的屏幕滾動操作不如 iPhone 流暢順滑,是什麼原因導致的?。
總的來講,前面的內容都沒問題:Android從最初就對Window級別的動畫用了硬體加速(在SurfaceFlinger用OpenGL ES繪製)。3.0開始View也可用硬體加速來繪製。

隨後這個答案里說多個窗口的不同進程中的GL上下文切換代價很高。

  • 首先,現在的GPU一般都有MMU,可以方便的切換上下文。
  • 其次,大部分的情況下,Android都只有一個需要GL繪製的窗口,就是當前使用的app窗口。其他顯示的窗口如狀態欄,在沒有內容更新的時候是不需要繪製的,SurfaceFlinger上已經存儲著上一次繪製的結果。
    答案里提到了窗口內容「最後的組合」,這個是每幀都要做的,只是,SurfaceFlinger在大部分情況下是用的Hardware Composer以overlay的方式來合成的,並不需要OpenGL ES,在不滿足Hardware Composer合成條件的情況下才會用OpenGL ES合成。Hardware Composer比OpenGL ES的方式性能更好、耗電更低。(我們有過測試,我們的數據是耗電大概少20%)。
    這裡再說一下究竟哪些情況是可以用Hardware Composer來合成的,Android對廠商的建議是有虛擬鍵的應支持4層合成(常規的桌面:壁紙+桌面+狀態欄+虛擬鍵),沒有虛擬鍵的是3層。這可以看出在桌面上放一個第三方app的懸浮窗口對性能及耗電是有不小影響的。

隨後答案提到渲染2.5次的數據。是的,我曾在某Google工作人員博客或是官方文檔里看到這樣的說法,建議我們每個窗口渲染的像素數不要超過窗口大小的2.5倍。
於是我寫了個程序測試每幀繪製全屏圖片N次時的幀率。
測試程序:http://files.cnblogs.com/zhucai/TestGraphics.apk
源碼:http://files.cnblogs.com/zhucai/TestGraphics_src.zip
大家都可以下載這個程序測試自己手機的表現結果。主要測試像素渲染性能、紋理載入性能。(點擊「開始測試」後,中間的數字是最近1秒繪製的幀數,通常越大越好。)
我的測試結果是在米2上可以繪製18次全屏圖像仍然滿幀率。在米4上繪製21次仍然是滿幀率。
可以看到現在的GPU渲染性能是非常好的。單純的渲染像素數量不會是瓶頸。(當然,可以的話還是渲染內容越少越好。)

最後答案說:後台程序優先順序低,它們滿打滿算也無法佔用超過 10% 的 CPU 資源。
於是我又寫了個測試程序:http://files.cnblogs.com/zhucai/TestBackgroundProcess.apk
源碼:http://files.cnblogs.com/zhucai/TestBackgroundProcess_src.zip
(點擊「啟動線程」後按HOME鍵退出,看其他app是否使用流暢。按Back退出也行,不過會有內存泄露。)
測試結果發現後台進程的CPU佔用的確被限制了,對其他app的UI流暢性影響很小。
不過可惜,Android的設計一直是本著開放的態度,它允許我們自己把自己聲明為前台進程(測試程序中點擊「啟動前台服務」),雖然被切換到後台了,可還是按前台進程來對待。經測試,這時候其他app的界面卡得一塌糊塗。桌面滑動非常卡。
順便說一下,這種把自己聲明為前台進程的程序,第三方app沒ROOT的話是殺不死它的。在MIUI里,則可以被「最近任務」界面的上劃圖標或一鍵清理給殺死的。(想到了MIUI 6安全中心的一句台詞:系統級的安全)


對於Android系統的流暢性,Android確實為之做了很多努力,如:窗口級動畫早就是硬體加速,Android3.0開始View級繪製也支持硬體加速,Android4.1使用VSync和3緩衝,SurfaceFlinger的overlay機制,等等。

但Android的坑也很多:

  • 垃圾回收時會暫停所有線程,碰到幾乎必然卡幀。(最近改善:4.4允許圖片在不同大小時重用;ART改善垃圾回收。)
  • 上面說了渲染像素是非常快的,可是紋理載入則是非常慢的。上面提到米2可以繪製18次全屏圖像保持滿幀率,可如果每幀都修改則只能承受一張的全屏圖像,當有2張全屏圖像每幀都修改的話就達不到滿幀率了。(測試程序選上「每幀修改圖片」可以測試這個。)基於這個原因,頻繁修改的軟體層View慎用。
  • 設置View的alpha會導致每次發生離屏緩衝。(最近改善:大概是4.2開始可以設置為alpha不導致離屏緩衝)
  • Canvas的saveLayer不加CLIP_TO_LAYER_SAVE_FLAG則會有個Texture Copy方法非常耗時。某些情況下設置alpha等也會碰到。
  • 某些情況下碰到quickReject失效時會嘗試繪製不在屏幕上的元素。
  • 等等。

總之,在Android上實現功能比較容易,但如果默認實現有了性能問題,要想解決就不好說了,有時候要繞很遠,有時候甚至繞不過去。

===============================================================

註:第一個測試程序里「圖片數量」大於一定值(我的米2是13)的時候幀率會大幅降低,這是因為超過了紋理緩存最大值。

相關鏈接:
Android圖形架構(繪圖慢一幀的事情這裡有說):http://source.android.com/devices/graphics/architecture.html
Android Performance Case Study:http://www.curious-creature.org/docs/android-performance-case-study-1.html


其實我覺得最主要還是開發者對於應用的優化不夠,太多的Overdraw和Layout方面的問題,Android開發者本身為了適配屏幕解析度和解決其他一些兼容性問題已經耗費很多精力了,很少有開發者會花很多精力去做細緻的性能優化,有的甚至連優化的方向都不知道。現在的官方微博客戶端要我看在Overdraw方面還是很嚴重,然後在非同步載入圖片的時候幀率也不夠穩定,算不上流暢。再則由於Android平台本身機能沒有強大到優化爛的應用也能跑的非常流暢暴露了優化不夠的事實,特別是手機廠商的定製ROM相比原生系統都一定程度犧牲了一些流暢性導致這個問題顯露的更加明顯,所以在Android上面作出流暢的應用要付出比iOS更多的精力。

其實Google這些年一直在系統層面作出努力提升系統的UI性能,從硬體加速到Project Butter到ReorderMerge繪圖操作等等,但是我感覺Google對於Android開發最佳實戰宣傳不夠,國內有多少開發者上Youtube看過I/O大會上面的Android Session?幾乎每年都有講關於系統圖形性能方面的Session。所以這裡面也有國內開發者開發水平和眼界的問題。

綜上所述:一是受限於Android平台本身性能不夠強大做出相同流暢度的應用比iOS更加困難,二是國內開發者對於Android開發性能優化方面的最佳實踐知之甚少。

update:
某些答案中說屏幕觸摸反應速度是影響流暢度最大問題的回答並不靠譜。我本身是做Android應用程序開發的,我舉一個例子就能質疑這個結論:為什麼原生系統(比如運行Android4.4的Nexus5)上面自帶的App能運行得絲般順滑而第3方開發的應用(特別是國內應用)就普遍比較卡?他們的運行環境是一樣的吧?屏幕也是一樣的吧?為什麼流暢度就硬是差一些呢?原因就是SystemApp是Google開發的,他們的開發人員了解如何做出性能優秀的應用,了解Andorid開發的最佳實踐。而第3方的開發者水平參差不齊,優化經驗不如Google開發人員,導致寫出的應用運行效率也不如SystemApp,站在同一個系統和運行環境裡面講,這就是最主要的原因。

上面的一些測試,能反映的最多也只是當手指觸摸到屏幕的那個瞬態反應的延遲,並不能完全說明Android不如iOS流暢的原因。我覺得流暢性主要表現再2個方面:一個是觸摸反應延遲,一個是渲染的幀率,而且後一個的重要性更大。可以想像一下從手指開始觸摸屏幕到UI開始滑動的那100ms的延遲給你造成的不流暢感覺大,還是在滑動過程中不穩定幀率造成的卡頓感覺大?其實Google這些年的Android版本更新也一直致力於改善屏幕觸摸延遲(找了個4.4的更新介紹有興趣的可以看看:Android - 4.4 KitKat),雖然可能還是比不上iOS,但是我覺得在這方面的差距已經很微小,帶來的感受上的差異也是很微妙不容察覺。

更多的不流暢性還是體現在優化爛的應用運行不穩定的幀率上面,比如在某個瞬態後台線程非同步載入圖片完成後在UI進程執行某個callback方法要顯示,如果圖片太大就需要根據ScaleType實時縮放到適合的尺寸顯示到ImageView上面,這個時候如果圖片太大縮放操作時間太長就有可能造成主線程阻塞較長時間,影響了系統UI進程在單位時間片內的渲染,導致掉幀。我再舉一個例子也能反駁屏幕觸摸反應速度是影響流暢度最大問題的觀點:為什麼在滑動顯示單行文字的列表項一般不會覺得卡,而顯示比較複雜布局的列表項(如微博)會比較卡?他們的屏幕和運行環境是一樣的吧?觸摸延遲都存在吧?為什麼呢?這是由於列表項的布局過於複雜,UI控制項在整個繪製的過程中(onMeasure()測量大小-&>onLayout()分配位置-&>onDraw()繪製)會花費更多的時間,比如各UI控制項之間的相對位置和大小可能是互相影響的,這就導致在渲染每一幀的時候需要更多的時間來計算大小和確定位置,然後繪製階段也需要多執行一些繪圖操作來畫完所有的UI控制項。面對複雜的界面,有經驗的開發者會盡量去避免界面的Overdraw(過渡繪製),減少UI層級,選用性能更好的ViewGroup(比如FrameLayout性能比LinearLayout好,LinearLayout性能比RelativeLayout性能好,但是布局能力最強大適應性最好的是RelativeLayout,在功能實現和性能優化中平衡達到最優需要經驗),避免圖片實時縮放,避免在調用頻繁的關鍵的路徑創建對象減少gc頻率,合理的管理Bitmap大對象(LruCache)等等(當然還有其他一些優化技巧不在此一一列舉了)。還有講什麼進程優先順序問題的答案說的也不是最主要的原因,Android的UI渲染進程的優先順序可能不是最高但也是比較高的,不會說他UI渲染優先順序設置到比後台線程還低的情況,這點不用過度討論,Google也沒蠢到那種地步,不服自己去看Android SDK源代碼。

我不否認屏幕觸摸延遲也是造成Android滑動感覺不流暢的原因之一,但是站在一個開發者看到的角度來講,我覺得在現有Android最新版本的系統優化下,他的影響遠沒有應用優化爛帶來的影響大,優化好的Android應用跑在最新的Android版本上基本可以運行的跟iOS應用一樣流暢。


我是來告訴暫時排名第一的 @Federico Mo ,數據陳舊是要不得的。

具體看原文:http://www.dazeinfo.com/2014/04/14/htc-one-m8-apple-iphone5s-fastest-touch-response-time-sales-q1-2014/
覺得不跟手是屏幕響應時間問題為主還是軟體優化問題為主,應該可以判斷了。

=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=

寫了這個回答,是為了指明當時排第一的 @Federico Mo 的回答中,作為論據的客觀測試數據太過陳舊,無法支撐其論點。那時 @Federico Mo 的答案在眾多不帶思考的贊同下扶搖直上,甩所有答案一大截,我覺得對大家的誤導過大所以寫了這個沒有真正回答題主問題本身的回答。就問題本身而言,推薦各位看 @劉長曦 的專欄和 @邑封 的回答。


我所知道的有兩方面問題:
1、Android是個設計比較現代的系統,所有程序都運行在獨立的沙盒中,以保證安全性和系統的穩定性。比如我現在在打字這個屏幕中,顯示著狀態欄這個程序,知乎這個程序以及虛擬鍵盤這個程序。用戶看到的每個界面都是系統把所有需要顯示的程序的界面合成之後呈現的。這個過程比傳統操作系統複雜,因此延遲較高,而且早期手機GPU還不支持多目標2D加速故不能有效地使用GPU,因此卡頓。即使到4.4的今天,動畫幀數仍然是個話題,所以屏幕合成還是比較消耗性能的。
這一點 @邑封 的答案比較準確詳實
2、Dalvik VM的垃圾回收存在卡頓現象,而Android單個進程允許的內存比較小,所以滾動列表需要不停地釋放內存和載入新內容,也就格外容易感到卡。ART顯著降低垃圾回收內存消耗,應該是值得期待的。WP對程序內存使用也有較多限制,所以有各種「載入中」,並且早期列表滾動很卡。


你們只看到了開發者,忽視了手機。大多數手機的屏幕調教決定了不可能跟手。不信去開發者選項勾選顯示觸摸操作,然後快速在屏幕上亂畫,你看那個圓點的運動軌跡。大多數都不跟手。這種手機應用再好也會有影響的。


咱覺得這版微博優化還行,硬體加速、圖片延遲載入都有,我手邊三年前的機器都能跑到滿幀。題主可以去下個 FPS Meter(測幀數的,需要 ROOT 許可權,MIUI 需要允許懸浮窗),然後再去刷你的微博,滾動時右上角接近 60FPS 的話,@Draco Leo 的答案就很可能是最符合你的提問的 —— 問題在於手機屏幕調教,而不在 App 開發者。

其實只要是觸屏,都肯定會有輕微的延遲。可以嘗試在開發者選項里把「顯示觸摸操作」打開,然後手指在屏幕上畫圈,不需要很快 —— 如果完全沒有延遲的話,圓點就應該可以一直被手指遮住 —— 但實際上,無論是什麼 Android 設備,一定可以看得到指示觸摸的圓點。

以及,在滿幀情況下的這種「滑動不跟手」,還有可能是軟體本身就是這麼設計的滾動演算法 —— 比如有幾個版本的 Sense 里自帶相冊的縮放和滑動都不跟手得很誇張;比如在 GO 桌面的設置里,你可以把滑動速度調到最慢,就會發現雖然流暢依舊,但明顯不跟手;又比如 Wacom 的「捲動」,也是可以按個人喜好,使滾動視圖完全不跟手(更快或者更慢)。


對於電容屏而言,屏幕採集到手的「軌跡」,其實是一系列連續的點。如果在 Android 的開發者選項里打開「指針位置」,快速地在屏幕上劃一下(劃完後手指離開屏幕),在末端會看到有軌跡不止一條:

藍色那個就是屏幕採集的實際軌跡(可以看到是幾個點連接成的),紫色的是推算的「手指離開屏幕」過程的平滑軌跡。// (由於看不出軌跡隨時間的變化過程,這個並不能解釋滾動視圖不跟手的現象。)


顯然,無論是哪個次元的演算法,不經過幾個採集周期,就無法得到紅色的平滑曲線。滾動要做到平滑流暢,也是要對多個採集點上的速度做平均,所以某種意義上,完全的「跟手」是不存在的 —— 只不過是 iOS 設備的軟硬體都足夠優秀,這一過程處理得足以讓人的感官認為是「跟手」的。


類似這樣的「考慮到硬體採集的觸摸軌跡本身不平滑,於是延遲一段時間來算平滑軌跡」的設計還有——


其實就是系統架構的問題啊。安卓越來越成熟,現在N5一樣流暢了。另外蘋果的gpu 比安卓更強大,所以在針對界面圖畫反應速度更優秀。不是屏幕材質的原因。


硬體:iPhone的屏幕響應速度比絕大多數Android手機都要快

應用:由於Android對第三方應用限制寬鬆,一些應用使用了非官方控制項,代碼優化不好會嚴重影響反應速度。這方面國產應用最多

系統:Android手機廠商大都對系統進行了定製,如果只是改改顏色、按鈕樣式對應用影響不大,但很多定製ROM會改變一些系統底層文件,從而影響第三方應用運行,比如smartbar。

版本:Android手機有多個版本分布,雖然Google play services能為低版本系統提供最新API支持,但國內手機大都不帶Google apps,新版本應用對低版本系統的支持度肯定不好。

說這麼多,其實我想說的是,手機硬體發展到今天,除非你買了個四五百塊錢的Android手機,不然流暢性已經不會影響你使用Android手機的體驗了,普通用戶也感覺不出來那幾十毫秒差別的響應速度。


iOS解決卡頓問題的兩大絕技:

一個是延長動畫時間,讓人感覺如德芙般絲滑的同時忘記其實是個Loading過程,只不過比Android的轉圈圈processbar好看多了。

另一個就是切回程序時先顯示上次退出的截圖,偷偷再載入程序,讓人覺得卧草好屌啊瞬間秒開有木有!


額,回答好多人啊,看來我程序員屌絲大軍還是很可觀的。回答一下吧,你的旗艦機的解析度不知道要比10年的小蘋果大多少了,一點可比性都沒有。雖然代碼效率有一定關係,但主要還是解析度。


試了一下,iOS和Android下上下拖動網頁感覺不出來明顯的不同,倒是兩指縮放,iOS明顯要快一些,能達到跟手的頻率至少比Android高1/2。

不過還是要看不同的應用的,應用寫不好怎麼都白搭,比如最近搜狐視頻iOS客戶端就卡得要命,每次點擊都需要2分鐘的時間才有反應。


我自己用的nexus5,很流暢,微博這個軟體就可以看出,用weico和fuubo很流暢,Google+更是如此,但是換成官方的,呵呵。所以我覺得還是app不用心和一些第三方rom自帶軟體太多導致的


就是個代碼水平的問題,iOS的App也有一划就卡的要死的。代碼優化過之後Android的App也可以非常流暢,你可以試試Google的原生應用和國外那些知名的Android應用,用著都很舒服。國內廠商只是懶,又捨不得花錢花精力罷了。


這不是性能問題,是設計問題。「跟手」和「流暢」不是可測量的參數,而是人的心理感覺。光看觸屏響應時間不能說明哪個更流暢,正如 1300 萬像素的攝像頭拍出的照片不一定比 800 萬像素的攝像頭好。


系統問題 android在界面上觸摸感覺界面滑動很輕盈 這就是跟手 在android有點沉重 在系統自帶的設置里就能感覺到 特別是在設置里的應用程序里 打開這個界面是會計算程序大小 需要大量讀寫存儲器 不跟手更加明顯 。android程序可以優化到不卡 但是還是比不上ios跟手 這是系統問題 多任務和ui處理優先順序等原因造成的。


這是應用設計水平問題。

Android裡面什麼渣應用都能過審核都能上架,所以開發商通常不自覺的降低了對Android應用性能的優化。實際上只要用心優化,Android應用一樣可以很跟手,只不過大多數產商沒動力做而已。

親兒子裝google原生應用是很稱手的,一部分對Android很認真的開發者也開發出了在Android下體驗很好的應用。…………只不過這些開發者一般就沒怎麼在意iOS版本而已。

開發者的能力是有限的,傾向性是明顯的,ios版做得好的應用,Android版本經常不認真做,而Android版做得好的應用,iOS版很可能沒有或者很簡陋。


瀏覽過全部答案和評論,我只是發現一個很好玩的現象

開發者基本都承認是系統問題。系統優先度,和API調用處理都不一樣。
即使是直接調用系統API完成的應用,也跟IOS相差一些。請問我該怎麼優化?
然而回答被反對。

而使用者大多指責說是開發者的問題,優化不夠,市場不對,或者價格問題。

對於說市場的,別把谷歌商店吹的太神了。
我就想指教一件事,同樣是QQ在google appstore下載跟我在豌豆莢下載有什麼區別么?


舉個相機的例子,ip的相機點擊對焦後,屏幕上很快出現對焦的符號,但是對焦聲音卻是在後面,說明什麼,說明ip為了讓人感覺良好做了點小動作,至於這樣做好不好,不好說,強迫症患者估計不會這麼認為。


推薦閱讀:

4G LTE 速度這麼快,普通的儲存設備能支持如此快的寫入速度嗎?
Moto G 的使用體驗如何?
小米能走多遠?
OPPO 是個怎樣的公司?
坐飛機為什麼要關手機?

TAG:iPhone | iOS | Android 手機 | Android | 手機屏幕 |