频道栏目
首页 > 程序开发 > 移动开发 > 其他 > 正文
浅析onWindowsFocusChanged()方法
2017-07-11 10:56:19         来源:a282255307的博客  
收藏   我要投稿

内容

概述

从字面上来讲,onWindowsFocusChanged()方法是指当窗口焦点变化的时候;从意义来说,onWindowsFocusChanged()就是指当前的Activity的Windows(窗口)获取或者失去焦点时这个方法就会被调用,并且当回调这个方法时,Activity是完全可见的。

在Activity生命周期中,onStart(), onResume(), onCreate()都不是布局visible的时间点,真正的visible时间点是onWindowFocusChanged()函数被执行时。从onWindowFocusChanged()被执行起,用户可以与应用进行交互了,换句话说,如果你想要在Activity加载后做些操作,可以在这个方法里调用而这之前,对用户的操作需要做一点限制。

onWindowFocusChanged()的使用情景与作用

根据介绍可以了解,onWindowFocusChanged()使用于以下等情景:

首次进入一个Activity后会在onResume()方法后面调用;

从Activity 跳到另一个Activity,新的窗口会获取焦点, 就的Activity的窗口会失去焦点;

打开软键盘进行输入时,窗口失去焦点;

软键盘输入完毕消失时,窗口重新获取焦点;

应用进入后台,窗口失去焦点;

应用从后台返回当前, 窗口重新获取焦点;

因此其可以有如下作用:

监控一个Activity是否载完毕;

在Activity加载后进行一些操作,如获取手机屏幕的高度和宽度;

当Activity挂起或恢复时,可以在方法内进行一些数据的保存或恢复的操作;

onWindowFocusChanged()调用详解

介绍完onWindowFocusChanged()基本的使用情景以及作用后,撸个demo来看下onWindowFocusChanged()具体的调用情况。

首先在Activity中重写的onWindowFocusChanged()方法如下:

/**  
   * 添加窗体在视图初始化完成过后  
   *  
   * @param hasFocus  
   */  
  @Override  
  public void onWindowFocusChanged(boolean hasFocus) {  
      super.onWindowFocusChanged(hasFocus);  
      if (hasFocus) {  
         //add Window.....  
      }  
  }  

其中参数hasFocus表示窗口是否获取或失去焦点,true表示获取焦点,false表示失去焦点。

然后我们看下总体的代码:

public class WindosFoucesDemo extends AppCompatActivity {

    private static final String TAG = "LifeCycleDemo";


    //Activity创建时被调用
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "onCreate is called.");
        setContentView(R.layout.activity_main);
    }


    //Activity创建或者从后台重新回到前台时被调用
    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "onStart is called.");
    }


    //Activity创建或者从被覆盖、后台重新回到前台时被调用
    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "onResume is called.");
    }

    //Activity窗口获得或失去焦点时被调用,在onResume之后或onPause之后
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(hasFocus){
            Log.i(TAG, "onWindowFocusChanged is called and" + "hasFocus is true");
        }else {
            Log.i(TAG, "onWindowFocusChanged is called and" + "hasFocus is false");
        }

    }

    //Activity被覆盖到下面或者锁屏时被调用
    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "onPause is called.");
        //有可能在执行完onPause或onStop后,系统资源紧张将Activity杀死,所以有必要在此保存持久数据
    }

    //退出当前Activity或者跳转到新Activity时被调用
    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "onStop is called.");
    }

    //退出当前Activity时被调用,调用之后Activity就结束了
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestory is called.");
    }


    //Activity从后台重新回到前台时被调用
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "onRestart called.");
    }
}

运行该Demo,查看Log日志,可以得到以下日志结果。

1. 启动Activity时:

image

2. 按下任务栏键,Activity被遮挡时:<喎"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxpbWcgYWx0PQ=="image" src="/uploadfile/Collfiles/20170710/201707100947351297.png" title="\" />

注意:按锁屏键和按任务栏或者Home键的生命周期是不同的,按Home执行onPause –> onStop –> onRestart –> onStart —> onResume 按锁屏键和对话框覆盖界面的生命周期是一样的,都只会进行onPause --> onResume .不会执行onStop,onRestart,onStart。

3. Activity恢复到前台时:

image

4. Activity退出时:

image

从上面的例子以及结果可以清楚的onWindowFocusChanged()在整个Activity生命周期内的调用情况,可以根据这些结果,在开发中来充分利用onWindowFocusChanged()方法的作用。

通过Activity源码去查看,发现onWindowFocusChanged()这个方法出现在WindowCallbackWrapper.java和View.java这两个类中,而WindowCallbackWrapper.java中其实也是调用View.java中的onWindowFocusChanged(),其代码如下:

     /**
     * Called when the window containing this view gains or loses focus.  Note
     * that this is separate from view focus: to receive key events, both
     * your view and its window must have focus.  If a window is displayed
     * on top of yours that takes input focus, then your own window will lose
     * focus but the view focus will remain unchanged.
     *
     * @param hasWindowFocus True if the window containing this view now has
     *        focus, false otherwise.
     * 当前的window(窗口)获取或者失去焦点的时候会回调这个方法.请注意,这个焦点和
     * view焦点是分离的,为了获取按键事件,view和view所在的窗口都必须获得焦点.如果 * 一个窗口处于你的输入事件的最上层,那么该窗口将失去焦点而view的焦点会保持不
     * 变.
     */
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        //获取软键盘a system window such as the keyguard may 
        InputMethodManager imm = InputMethodManager.peekInstance();
        if (!hasWindowFocus) {
            if (isPressed()) {  
                //键盘有按下事件,则强制将该view包含的所有子控件全部setPressed()设置为false
                setPressed(false);
            }
            if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
                //这是一个隐藏的方法(带@hide标签),当view失去焦点时会调用该方法
                imm.focusOut(this);
            }
            //移onWindowFocusChanged(boolean hasFocus) 被回调的触发时机是窗口获取或失去焦点的时候.除长按事件回调的接口方法
            removeLongPressCallback();
            //移除轻触探测器,源码中叫 "Remove the tap detection timer."
            removeTapCallback();
            //当焦点(fucos)从按下变成取消的时候会调用,属于隐藏方法
            onFocusLost();
        } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
            //当view获得焦点时调用该方法,属于隐藏方法
            imm.focusIn(this);
        }
        //强制view刷新drawable state,并且会回调drawableStateChanged()方法
        refreshDrawableState();
    }

从源码可以验证出,onWindowFocusChanged()方法被回调的触发时机是窗口获取或失去焦点的时候。并且在onResume()方法中的官方解释 Use {@link #onWindowFocusChanged} to know for certain that your activity is visible to the user (for example, to resume a game). 可以知道onWindowFocusChanged()第一次调用是在onResume()方法后面。

点击复制链接 与好友分享!回本站首页
上一篇:微信小程序picker中range-key中必须带单引号
下一篇:通过源码详解 Servlet
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站