初识onWindowFocusChanged(boolean hasFocus)

来源:互联网 发布:小学语文网络研修计划 编辑:程序博客网 时间:2024/06/05 03:08

之前对于Activity只关心它主要的生命周期函数,如onCreate()、onStart()、onResume()等,忽略了onWindowFocusChanged(boolean hasFocus)这个方法的存在。

但是在后来的学习中才逐渐了解到onResume()表示的是Activity处于运行期这样一种状态,它只是表示一种状态,而onWindowFocusChanged()则表示当前Activity获得或者失去焦点,当回调了这个方法时表示Activity是完全对用户可见的(只是可见,但是界面上还是一片黑呼呼的,有待draw..) 因此如果要统计Activity的渲染时间就可以使用这个方法作为渲染的结束时间。

在Activity生命周期中,onStart, onResume, onCreate都不是真正visible的时间点,真正的visible时间点是onWindowFocusChanged()函数被执行时。译注:从onWindowFocusChanged被执行起,用户可以与应用进行交互了,而这之前,对用户的操作需要做一点限制。

相信开发者都遇到过这样一种情况:经常会用到view的getWidth()、getHeight() 方法来获取该view的宽和高,如果是在onCreate()或者onResume()中调用返回的值经常都是0。

如果这个view的长宽很确定不为0的话,那么出现这种情况很可能是你过早的调用了这些方法,也就是说在这个view被加入到rootview之前你就调用了这些方法,返回的值自然为0。

解决这个问题的方法有很多,比如延缓调用这些获取宽高的方法,其中我觉得比较简单的一种方法就是在onWindowFocusChanged()中去获取控件View的width、height等信息(尤其适用于那种必须在Activity渲染完成后立马获取View宽高信息的情况)。

下面通过一个demo显示下Activity详细的生命周期:

布局文件activity_main.xml:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.monkey.testwindowsfocus.MainActivity">    <com.example.monkey.testwindowsfocus.CustomImageView        android:layout_width="100dp"        android:layout_height="100dp"        android:src="@mipmap/ic_launcher"        android:scaleType="centerCrop"        android:id="@+id/btn_switch"/></RelativeLayout>

在布局文件中使用了一个自定义的CustomImageView,代码如下:

package com.example.monkey.testwindowsfocus;import android.content.Context;import android.graphics.Canvas;import android.util.AttributeSet;import android.util.Log;import android.widget.ImageView;/** * Created by monkey on 2016/12/26. */public class CustomImageView extends ImageView{    public CustomImageView(Context context) {        super(context);    }    public CustomImageView(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        Log.i(MainActivity.TAG, "onMeasure ");    }    @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        Log.i(MainActivity.TAG, "onLayout ");    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        Log.i(MainActivity.TAG, "onDraw ");    }}

注:为了方便MainActivity和SecondActivity共用同一个布局文件,在MainActivty中点击CustomImageView跳转到SecondActivity。
MainActivity:

package com.example.monkey.testwindowsfocus;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;public class MainActivity extends AppCompatActivity {    public static final String TAG = "TAG";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.i(TAG, "MainActivity onCreate ");        initView();    }    private void initView() {        CustomImageView ivSwitch = (CustomImageView)findViewById(R.id.btn_switch);        ivSwitch.addOnLayoutChangeListener(                new View.OnLayoutChangeListener() {                    @Override                    public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {                        Log.i(TAG, "MainActivity onLayoutChange ");                    }        });        ivSwitch.setOnClickListener(                new View.OnClickListener() {                    @Override                    public void onClick(View view) {                        Intent intent = new Intent(MainActivity.this,SecondActivity.class);                        startActivity(intent);                    }                }        );    }    @Override    public void onAttachedToWindow() {        super.onAttachedToWindow();        Log.i(TAG, "MainActivity onAttachedToWindow ");    }    @Override    public void onDetachedFromWindow() {        super.onDetachedFromWindow();        Log.i(TAG, "MainActivity onDetachedFromWindow ");    }    @Override    public void onWindowFocusChanged(boolean hasFocus) {        super.onWindowFocusChanged(hasFocus);        Log.i(TAG, "MainActivity onWindowFocusChanged  hasFocus--->"+hasFocus);    }    @Override    protected void onStart() {        super.onStart();        Log.i(TAG, "MainActivity onStart ");    }    @Override    protected void onResume() {        super.onResume();        Log.i(TAG, "MainActivity onResume ");    }    @Override    protected void onRestart() {        super.onRestart();        Log.i(TAG, "MainActivity onRestart ");    }    @Override    protected void onPause() {        super.onPause();        Log.i(TAG, "MainActivity onPause ");    }    @Override    protected void onStop() {        super.onStop();        Log.i(TAG, "MainActivity onStop ");    }    @Override    protected void onDestroy() {        super.onDestroy();        Log.i(TAG, "MainActivity onDestroy ");    }}

SecondeActivity:

package com.example.monkey.testwindowsfocus;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;public class SecondActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Log.i(MainActivity.TAG, "SecondActivity onCreate ");        initView();    }    private void initView() {        CustomImageView ivSwitch = (CustomImageView)findViewById(R.id.btn_switch);        ivSwitch.addOnLayoutChangeListener(                new View.OnLayoutChangeListener() {                @Override                public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) {                    Log.i(MainActivity.TAG, "SecondActivity onLayoutChange ");                }        });    }    @Override    public void onAttachedToWindow() {        super.onAttachedToWindow();        Log.i(MainActivity.TAG, "SecondActivity onAttachedToWindow ");    }    @Override    public void onDetachedFromWindow() {        super.onDetachedFromWindow();        Log.i(MainActivity.TAG, "SecondActivity onDetachedFromWindow ");    }    @Override    public void onWindowFocusChanged(boolean hasFocus) {        super.onWindowFocusChanged(hasFocus);        Log.i(MainActivity.TAG, "SecondActivity onWindowFocusChanged hasFocus--->"+hasFocus);    }    @Override    protected void onStart() {        super.onStart();        Log.i(MainActivity.TAG, "SecondActivity onStart ");    }    @Override    protected void onResume() {        super.onResume();        Log.i(MainActivity.TAG, "SecondActivity onResume ");    }    @Override    protected void onRestart() {        super.onRestart();        Log.i(MainActivity.TAG, "SecondActivity onRestart ");    }    @Override    protected void onPause() {        super.onPause();        Log.i(MainActivity.TAG, "SecondActivity onPause ");    }    @Override    protected void onStop() {        super.onStop();        Log.i(MainActivity.TAG, "SecondActivity onStop ");    }    @Override    protected void onDestroy() {        super.onDestroy();        Log.i(MainActivity.TAG, "SecondActivity onDestroy ");    }}

点击App图标后的生命周期如下:
com.example.monkey.testwindowsfocus I/TAG: MainActivity onCreate
com.example.monkey.testwindowsfocus I/TAG: MainActivity onStart
com.example.monkey.testwindowsfocus I/TAG: MainActivity onResume
com.example.monkey.testwindowsfocus I/TAG:
MainActivity onAttachedToWindow
com.example.monkey.testwindowsfocus I/TAG: onMeasure
com.example.monkey.testwindowsfocus I/TAG: onMeasure
com.example.monkey.testwindowsfocus I/TAG: onMeasure
com.example.monkey.testwindowsfocus I/TAG: onMeasure
com.example.monkey.testwindowsfocus I/TAG: onLayout
com.example.monkey.testwindowsfocus I/TAG: MainActivity onLayoutChange
com.example.monkey.testwindowsfocus I/TAG:
MainActivity onWindowFocusChanged hasFocus—>true
com.example.monkey.testwindowsfocus I/TAG: onDraw

点击CustomImageView启动SecondActivity:
com.example.monkey.testwindowsfocus I/TAG: MainActivity onPause
com.example.monkey.testwindowsfocus I/TAG:
MainActivity onWindowFocusChanged hasFocus—>false
com.example.monkey.testwindowsfocus I/TAG: SecondActivity onCreate
com.example.monkey.testwindowsfocus I/TAG: SecondActivity onStart
com.example.monkey.testwindowsfocus I/TAG: SecondActivity onResume
com.example.monkey.testwindowsfocus I/TAG:
SecondActivity onAttachedToWindow
com.example.monkey.testwindowsfocus I/TAG: onMeasure
com.example.monkey.testwindowsfocus I/TAG: onMeasure
com.example.monkey.testwindowsfocus I/TAG: onMeasure
com.example.monkey.testwindowsfocus I/TAG: onMeasure
com.example.monkey.testwindowsfocus I/TAG: onLayout
com.example.monkey.testwindowsfocus I/TAG: SecondActivity onLayoutChange
com.example.monkey.testwindowsfocus I/TAG:
SecondActivity onWindowFocusChanged hasFocus—>true
com.example.monkey.testwindowsfocus I/TAG: onDraw
com.example.monkey.testwindowsfocus I/TAG: MainActivity onStop

在SecondActivity页面点击返回键:
com.example.monkey.testwindowsfocus I/TAG: SecondActivity onPause
com.example.monkey.testwindowsfocus I/TAG: MainActivity onRestart
com.example.monkey.testwindowsfocus I/TAG: MainActivity onStart
com.example.monkey.testwindowsfocus I/TAG: MainActivity onResume
com.example.monkey.testwindowsfocus I/TAG:
MainActivity onWindowFocusChanged hasFocus—>true
com.example.monkey.testwindowsfocus I/TAG: onDraw
com.example.monkey.testwindowsfocus I/TAG:
SecondActivity onWindowFocusChanged hasFocus—>false
com.example.monkey.testwindowsfocus I/TAG: SecondActivity onStop
com.example.monkey.testwindowsfocus I/TAG: SecondActivity onDestroy
com.example.monkey.testwindowsfocus I/TAG:
SecondActivity onDetachedFromWindow

在MainActivity页面点击返回键:
com.example.monkey.testwindowsfocus I/TAG:
MainActivity onWindowFocusChanged hasFocus—>false
com.example.monkey.testwindowsfocus I/TAG: MainActivity onPause
com.example.monkey.testwindowsfocus I/TAG: MainActivity onStop
com.example.monkey.testwindowsfocus I/TAG: MainActivity onDestroy
com.example.monkey.testwindowsfocus I/TAG:
MainActivity onDetachedFromWindow

0 0