初识onWindowFocusChanged(boolean hasFocus)

之前对于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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值