1. 程式人生 > >【問題分析】 為什麼設定了android:windowIsTranslucent屬性後Activity的退出動畫就不生效了

【問題分析】 為什麼設定了android:windowIsTranslucent屬性後Activity的退出動畫就不生效了

問題概述

當為Activity設定了android:windowIsTranslucent=true的style屬性後, 該Activity會變成一個透明視窗, 隨之而來的問題是Activity的退出動畫會不生效了, 哪怕在finish回撥中使用類似下面的程式碼為Activity配置自定義進入/退出動畫也無效

 

	public void finish() {
    	super.finish();
        this.overridePendingTransition(R.anim.xxx, R.anim.xxx);
    	}

 

網路上有很多文章從應用層給出了一些解決方案, 但沒有很好的解釋為什麼會發生透明視窗的退出動畫不生效的原因, 本文旨在從Android Framework (基於Android 7.0版本) 的概要流程來說明這個問題背後的原因.

 

Root Cause分析

 

 

如上面的兩張時序圖所示, 對比了同樣的一個Activity 在透明視窗屬性android:windowIsTranslucent分別為false和true的時候, 使用者按下Back鍵退出後發生在Android Framework completePaused時序中的差別, 從圖中可以清楚的看到, 透明視窗屬性為true導致ActivityStack finishCurrentActivityLocked函式中認為下一個要啟動的next Activity 是可見的(透明視窗r蓋著的就是next, 既然是被透明視窗蓋著那麼next當然是可見) , 所以會引起透明視窗r馬上就被排程destroy, 繼而導致該視窗被WindowManagerService銷燬, Activity視窗都沒有了, 自然也就談不上有退出動畫了.

 

網路上很多文章提供的解決方案是在應用裡面增加動畫style resource來解決透明視窗沒有退出動畫的問題, 該方案在Android Framework裡面的實現原理是什麼呢? 參考下面的時序圖

 

如上圖所示,關鍵點在於WindowManagerService removeWindowLocked有幾次機會去判斷視窗是否需要去執行animation動畫, 從而推遲從WindowManagerService中馬上銷燬視窗的邏輯, 當應用自己配置了退出動畫的style resource的時候, 就滿足了4) if 的條件, 退出了視窗的銷燬, 從而顯示了視窗退出動畫