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
關聯的生命周期流程圖: