<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 問題 - Q1:但是大伙想過沒有,這個 16.6刷新一次屏幕到底是什么意思呢?是指每隔 16.6ms 調用 onDraw() 繪制一次么? - Q2:如果界面一直保持沒變的話,那么還會每隔 16.6ms 刷新一次屏幕么? - Q3:界面的顯示其實就是一個 Activity 的 View 樹里所有的 View 都進行測量、布局、繪制操作之后的結果呈現,那么如果這部分工作都完成后,屏幕會馬上就刷新么? - Q4:網上都說避免丟幀的方法之一是保證每次繪制界面的操作要在 16.6ms 內完成,但如果這個 16.6ms 是一個固定的頻率的話,請求繪制的操作在代碼里被調用的時機是不確定的啊,那么如果某次用戶點擊屏幕導致的界面刷新操作是在某一個 16.6ms 幀快結束的時候,那么即使這次繪制操作小于 16.6 ms,按道理不也會造成丟幀么?這又該如何理解? - Q5:大伙都清楚,主線程耗時的操作會導致丟幀,但是耗時的操作為什么會導致丟幀?它是如何導致丟幀發生的? # 屏幕展示的顏色數據 >- 在GPU中有一塊緩沖區叫做 Frame Buffer ,這個幀緩沖區可以認為是存儲像素值的二位數組。 >- 數組中的每一個值就對應了手機屏幕的像素點需要顯示的顏色。 >- 由于這個幀緩沖區的數值是在不斷變化的,所以只要完成對屏幕的刷新就可以顯示不同的圖像了.。 >- 至于刷新工作手記的邏輯電路會定期的刷新 Frame Buffer的 目前主流的刷新頻率為60次/秒 折算出來就是16ms刷新一次。 ## GPU的Frame Buffer中的數據 >- GPU 除了幀緩沖區用以交給手機屏幕進行繪制外. 還有一個緩沖區 Back Buffer 這個用以交給應用的,讓CPU往里面填充數據。 >- GPU會定期交換 Back Buffer 和 Frame Buffer ,也就是對Back Buffer中的數據進行柵格化后將其轉到 Frame Buffer 然后交給屏幕進行顯示繪制,同時讓原先的Frame Buffer 變成 Back Buffer 讓程序處理。 # Android的16ms 在Android中我們一般都會提到`16ms`繪制一次,那么到底是那里控制這16ms的呢? 在`Choreographer`類中我們有一個方法獲取屏幕刷新速率: ```java public final class Choreographer { private static float getRefreshRate() { DisplayInfo di = DisplayManagerGlobal.getInstance().getDisplayInfo( Display.DEFAULT_DISPLAY); return di.refreshRate; } } /** * Describes the characteristics of a particular logical display. * @hide */ public final class DisplayInfo implements Parcelable { /** * The refresh rate of this display in frames per second. * <p> * The value of this field is indeterminate if the logical display is presented on * more than one physical display. * </p> */ public float refreshRate; } final class VirtualDisplayAdapter extends DisplayAdapter { private final class VirtualDisplayDevice extends DisplayDevice implements DeathRecipient { @Override public DisplayDeviceInfo getDisplayDeviceInfoLocked() { if (mInfo == null) { mInfo = new DisplayDeviceInfo(); mInfo.name = mName; mInfo.uniqueId = getUniqueId(); mInfo.width = mWidth; mInfo.height = mHeight; mInfo.refreshRate = 60; /***部分代碼省略***/ } return mInfo; } } } ``` 一秒60幀,計算下來大概16.7ms一幀。 # 屏幕繪制 作為嚴重影響Android口碑問題之一的UI流暢性差的問題,首先在Android 4.1版本中得到了有效處理。其解決方法就是本文要介紹的Project Butter。 Project Butter對Android Display系統進行了重構,引入了三個核心元素,即VSYNC、Triple Buffer和Choreographer。其中, VSYNC是理解Project Buffer的核心。VSYNC是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上已經很早就廣泛使用的技術。 可簡單的把它認為是一種定時中斷。 接下來,將圍繞VSYNC來介紹Android Display系統的工作方式。請注意,后續討論將以Display為基準,將其劃分成16ms長度的時間段, 在每一時間段中,Display顯示一幀數據(相當于每秒60幀)。時間段從1開始編號。 ## 沒有VSYNC的情況: ![](../images/沒有VSYNC的情況.png) 由上圖可知 1.時間從0開始,進入第一個16ms:Display顯示第0幀,CPU處理完第一幀后,GPU緊接其后處理繼續第一幀。三者互不干擾,一切正常。 2.時間進入第二個16ms:因為早在上一個16ms時間內,第1幀已經由CPU,GPU處理完畢。故Display可以直接顯示第1幀。顯示沒有問題。但在本16ms期間,CPU和GPU 卻并未及時去繪制第2幀數據(注意前面的空白區),而是在本周期快結束時,CPU/GPU才去處理第2幀數據。 3.時間進入第3個16ms,此時Display應該顯示第2幀數據,但由于CPU和GPU還沒有處理完第2幀數據,故Display只能繼續顯示第一幀的數據,結果使得第1 幀多畫了一次(對應時間段上標注了一個Jank)。 4.通過上述分析可知,此處發生Jank的關鍵問題在于,為何第1個16ms段內,CPU/GPU沒有及時處理第2幀數據?原因很簡單,CPU可能是在忙別的事情(比如某個應用通過sleep 固定時間來實現動畫的逐幀顯示),不知道該到處理UI繪制的時間了。可CPU一旦想起來要去處理第2幀數據,時間又錯過了! ## NSYNC的出現 為解決這個問題,Project Buffer引入了VSYNC,這類似于時鐘中斷。結果如圖所示: ![](../images/NSYNC的出現.png) 由圖可知,每收到VSYNC中斷,CPU就開始處理各幀數據。整個過程非常完美。 不過,仔細琢磨圖2卻會發現一個新問題:圖2中,CPU和GPU處理數據的速度似乎都能在16ms內完成,而且還有時間空余,也就是說,CPU/GPU的FPS(幀率,Frames Per Second)要高于Display的FPS。確實如此。由于CPU/GPU只在收到VSYNC時才開始數據處理,故它們的FPS被拉低到與Display的FPS相同。但這種處理并沒有什么問題,因為Android設備的Display FPS一般是60,其對應的顯示效果非常平滑。 如果CPU/GPU的FPS小于Display的FPS,會是什么情況呢?請看下圖: ![](../images/NSYNC的出現2.png) 由圖可知: 1.在第二個16ms時間段,Display本應顯示B幀,但卻因為GPU還在處理B幀,導致A幀被重復顯示。 2.同理,在第二個16ms時間段內,CPU無所事事,因為A Buffer被Display在使用。B Buffer被GPU在使用。注意,一旦過了VSYNC時間點, CPU就不能被觸發以處理繪制工作了。 ## 三級緩存 為什么CPU不能在第二個16ms處開始繪制工作呢?原因就是只有兩個Buffer。如果有第三個Buffer的存在,CPU就能直接使用它, 而不至于空閑。出于這一思路就引出了Triple Buffer。結果如圖所示: ![](../images/TripleBuffer.png) 由圖可知: 第二個16ms時間段,CPU使用C Buffer繪圖。雖然還是會多顯示A幀一次,但后續顯示就比較順暢了。 是不是Buffer越多越好呢?回答是否定的。由圖4可知,在第二個時間段內,CPU繪制的第C幀數據要到第四個16ms才能顯示, 這比雙Buffer情況多了16ms延遲。所以,Buffer最好還是兩個,三個足矣。 以上對VSYNC進行了理論分析,其實也引出了Project Buffer的三個關鍵點: 核心關鍵:需要VSYNC定時中斷。 Triple Buffer:當雙Buffer不夠使用時,該系統可分配第三塊Buffer。 另外,還有一個非常隱秘的關鍵點:即將繪制工作都統一到VSYNC時間點上。這就是Choreographer的作用。在它的統一指揮下,應用的繪制工作都將變得井井有條。 Android 平臺提供了三類動畫,一類是 Tween 動畫-Animation,即通過對場景里的對象不斷做圖像變換 ( 平移、縮放、旋轉 ) 產生動畫效果;第二類是 Frame 動畫,即順序播放事先做好的圖像,跟電影類似。最后一種就是3.0之后才出現的屬性動畫PropertyAnimator(在下文我們講幀動畫和補間動畫統一稱為View動畫)。如果有人對ViewGroup內部View使用過View動畫的還知道有layout-animation。 大家對這三種動畫基本都能熟練的使用,那么…...? - 想知道動畫與界面渲染與屏幕刷新有著什么樣的關系? - 想知道屬性動畫為什么會發生內存泄露么? 因為本文章中會有一些屏幕刷新、Vsync信號相關的知識點,讀過我寫的 [Android的16ms和垂直同步以及三重緩存](https://www.jianshu.com/p/3750db831aca) 和[Android系統的編舞者Choreographer](https://www.jianshu.com/p/fb645ea98474) 這兩篇文章的同學會可能會更容易了解本文章。 接下來拿起我們的鍵盤、鼠標和顯示器,我們將探索從Android源碼(android-23)的角度去探索動畫的實現~!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看