public void onWindowFocusChanged (boolean hasFocus)
參數hasFocus: the window of this activity has focus.
是指activity是否獲取或失去了focus,獲得到了該參數為true,否則為false。一般是進入或恢復Actiity時為true,Actvity銷毀或者退到后台則為false。
Called when the current Window of the activity gains or loses focus. This is the best indicator of whether this activity is visible to the user. The default implementation clears the key tracking state, so should always be called. Note that this provides information about global focus state, which is managed independently of activity lifecycles. As such, while focus changes will generally have some relation to lifecycle changes (an activity that is stopped will not generally get window focus), you should not rely on any particular order between the callbacks here and those in the other lifecycle methods such as onResume(). As a general rule, however, a resumed activity will have window focus... unless it has displayed other dialogs or popups that take input focus, in which case the activity itself will not have focus when the other windows have it. Likewise, the system may display system-level windows (such as the status bar notification panel or a system alert) which will temporarily take window input focus without pausing the foreground activity.
上面的官方的注解,大意是這個方法可以真正表示activity對用戶的可見。focus狀態處理是和activity的生命周期獨立的,但是有有相關性,比如一個停止了的activity一般不會獲取focus,也不依賴既定的聲明周期的回調函數如onResume()來確保這個focus的獲取。
一般一個resumed的activity會獲得焦點,除非它展示的dialog或者彈出框截取了focus,這時候activity只有在其他窗口釋放focus后才會獲取。類似的,系統也會優先顯示系統的窗口比附狀態欄通知或者系統alert,這些都會暫時取走焦點但是不會停止前台activity的狀態。
啰嗦了這么多,其實就是想說在這個監聽的函數里能做很多事情。
1.它的調用表示activity中的所有控件都已經准備好,可以進行UI交互了,這在其它生命周期函數里都無法判斷,常見的就是測量控件,獲取控件的寬高。
在onCreate()中使用一個view的getWidth() getHeight() 方法來獲取該view的寬和高,返回的值常常。解決該問題的方法有很多,主要就是延后調用這些方法。比如會使用主線程的postDelay的方法延遲獲取,會得到如果這個view的長寬。因為如果過早的調用View的getWidth等方法,也就是說在這個view被加入到rootview之前就調用了返回的值自然為0。但是延遲的方法總覺得時間控制上不那么可靠。
但可以在onWindowFocusChanged()里面調用這些方法來測量控件的size,是可以獲取到View的寬高的。還可以進行一些Activty進入時的控件的狀態默認設置。

@Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (!hasFocus) { // Activity失去焦點時不獲取 update by bianmaoran on v2.3.1 return; } // 在view繪制完畢后才能獲取到坐標 // 上傳照片顯示后重新獲取坐標 mBreakfastLayout.getLocationOnScreen(posBreakfast); mLunchLayout.getLocationOnScreen(posLunch); mDinnerLayout.getLocationOnScreen(posDinner); mOtherLayout.getLocationOnScreen(posOther); mDietaryRg.setOnCheckedChangeListener(new CheckedListener()); // 設置RadioButton的初始選中狀態 switch (mealType) { case 1: mDietaryRg.check(R.id.rb_breakfast); break; case 2: mDietaryRg.check(R.id.rb_lunch); break; case 3: mDietaryRg.check(R.id.rb_dinner); break; case 4: mDietaryRg.check(R.id.rb_other); break; default: break; } }
2.溫習一下Activity的生命周期(參考一篇描述詳盡的文章onWindowFocusChanged重要作用 and Activity生命周期)
1.啟動Activity:系統會先調用onCreate方法,然后調用onStart方法,最后調用onResume,Activity進入運行狀態。
2.當前Activity被其他Activity覆蓋其上或被鎖屏:系統會調用onPause方法,暫停當前Activity的執行。
3.當前Activity由被覆蓋狀態回到前台或解鎖屏:系統會調用onResume方法,再次進入運行狀態。
4.當前Activity轉到新的Activity界面或按Home鍵回到主屏,自身退居后台:系統會先調用onPause方法,然后調用onStop方法,進入停滯狀態。
5.用戶后退回到此Activity:系統會先調用onRestart方法,然后調用onStart方法,最后調用onResume方法,再次進入運行狀態。
6.當前Activity處於被覆蓋狀態或者后台不可見狀態,即第2步和第4步,系統內存不足,殺死當前Activity,而后用戶退回當前Activity:再次調用onCreate方法、onStart方法、onResume方法,進入運行狀態。
<所以一些頁面的數據在被殺后因為重新onCreate肯定會有丟失,這里的恢復和保存要有相應的處理方式,特別是與登錄狀態有關的數據,以后會討論到>
7.用戶退出當前Activity:系統先調用onPause方法,然后調用onStop方法,最后調用onDestory方法,結束當前Activity。
1.onWindowFocusChanged方法:在Activity窗口獲得或失去焦點時被調用,例如創建時首次呈現在用戶面前;當前Activity被其他Activity覆蓋;當前Activity轉到其他Activity或按Home鍵回到主屏,自身退居后台;用戶退出當前Activity。以上幾種情況都會調用onWindowFocusChanged,並且當Activity被創建時是在onResume之后被調用,當Activity被覆蓋或者退居后台或者當前Activity退出時,它是在onPause之后被調用。
這個方法在某種場合下還是很有用的,例如程序啟動時想要獲取視特定視圖組件的尺寸大小,在onCreate中可能無法取到,因為窗口Window對象還沒創建完成,這個時候我們就需要在onWindowFocusChanged里獲取。
2.onSaveInstanceState:(1)在Activity被覆蓋或退居后台之后,系統資源不足將其殺死,此方法會被調用;(2)在用戶改變屏幕方向時,此方法會被調用;(3)在當前Activity跳轉到其他Activity或者按Home鍵回到主屏,自身退居后台時,此方法會被調用。第一種情況我們無法保證什么時候發生,系統根據資源緊張程度去調度;第二種是屏幕翻轉方向時,系統先銷毀當前的Activity,然后再重建一個新的,調用此方法時,我們可以保存一些臨時數據;第三種情況系統調用此方法是為了保存當前窗口各個View組件的狀態。onSaveInstanceState的調用順序是在onPause之前。
3.onRestoreInstanceState:(1)在Activity被覆蓋或退居后台之后,系統資源不足將其殺死,然后用戶又回到了此Activity,此方法會被調用;(2)在用戶改變屏幕方向時,重建的過程中,此方法會被調用。我們可以重寫此方法,以便可以恢復一些臨時數據。onRestoreInstanceState的調用順序是在onStart之后。
當從后台會到前台時,系統先調用onRestart方法,然后調用onStart方法,最后調用onResume方法,Activity又進入了運行狀態。
參考文章: