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又进入了运行状态。
参考文章: