View
和 Activity
一样也是有着自己的生命周期方法,熟知这些生命周期方法对我们日常开发绝对会有不少帮助的(比如我最近遇到的一些自定义 View
的需求),下面我们通过自定义一个 View
来打印它的全部生命周期方法吧:
public class LifeView extends View {
private static final String TAG = "LifeView";
public LifeView(Context context) {
super(context);
}
public LifeView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public LifeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* View通过xml文件反射完成完成初始化时的回调
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
Log.e(TAG, "onFinishInflate()");
}
/**
* View关联到窗口(Activity)时的回调
*/
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Log.e(TAG, "onAttachedToWindow()");
}
/**
* View所在窗口(Activity)的可见性发生变化时的回调
*/
@Override
protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
Log.e(TAG, "onWindowVisibilityChanged() visibility is " + getVisibilityName(visibility));
}
/**
* View的可见性发生变化时的回调
*/
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
Log.e(TAG, "onVisibilityChanged() visibility is " + getVisibilityName(visibility));
}
private String getVisibilityName(int visibility) {
switch (visibility) {
case View.VISIBLE:
return "View.VISIBLE";
case View.INVISIBLE:
return "View.INVISIBLE";
case View.GONE:
return "View.GONE";
default:
return "View.VISIBLE";
}
}
/**
* 测量View时的回调
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.e(TAG, "onMeasure()");
}
/**
* View大小发生改变时的回调
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.e(TAG, "onSizeChanged() w is " + w + " , h is " + h + ", oldw is " + oldw + " , oldh is " + oldh);
}
/**
* 布局View及其子View布局位置大小时的回调
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.e(TAG, "onLayout() left is " + left + " , top is " + top + ", right is " + right + ", bottom is " + bottom);
}
/**
* 绘制View时的回调
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.e(TAG, "onDraw()");
}
/**
* View获取焦点或者失去焦点时调用
*/
@Override
protected void onFocusChanged(boolean focus, int direction, @Nullable Rect previouslyFocusedRect) {
super.onFocusChanged(focus, direction, previouslyFocusedRect);
Log.e(TAG, "onFocusChanged() focus is " + focus);
}
/**
* View所在窗口获取焦点或者失去焦点时调用
*/
@Override
public void onWindowFocusChanged(boolean windowFocus) {
super.onWindowFocusChanged(windowFocus);
Log.e(TAG, "onWindowFocusChanged() windowFocus is " + windowFocus);
}
/**
* View给窗口(Activity)移除时的回调
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
Log.e(TAG, "onDetachedFromWindow()");
}
}
然后我们在 Activity
中也加上打印:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "LifeView";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.w(TAG, "onCreate");
}
@Override
protected void onStart() {
super.onStart();
Log.w(TAG, "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.w(TAG, "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.w(TAG, "onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.w(TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.w(TAG, "onDestroy");
}
}
ok,我们来看打印的结果吧
Activity 启动时的打印
可以看到,View
的 xml 反射初始化完成后才轮到 Activity
的加载,如果能省去这一步,那么 Activity
将会更快完成加载。
而 View
是从 Activiy
的 onResume
方法之后才开始去进行测量绘制的,这也是为什么前期无法通过 View.getWidth/Height()
获取到宽高的原因
Activity 进入 pause / stop 时的打印
通过 View
的生命周期方法,我们可以清晰看到,当 Activity
进入 onPause
之前,Activity
已经失去了焦点,当进入 onStop
后, Activity
的可见性最终变成了 View.GONE
Activity 销毁时的打印
这个就简单明了,不用多说了
最后,附上 View
和 Activiy
关联的生命周期流程图: