天天看點

View與Activity之間不可不知的關系

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與Activity之間不可不知的關系

可以看到,

View

的 xml 反射初始化完成後才輪到

Activity

的加載,如果能省去這一步,那麼

Activity

将會更快完成加載。

View

是從

Activiy

onResume

方法之後才開始去進行測量繪制的,這也是為什麼前期無法通過

View.getWidth/Height()

擷取到寬高的原因

Activity 進入 pause / stop 時的列印

View與Activity之間不可不知的關系

通過

View

的生命周期方法,我們可以清晰看到,當

Activity

進入

onPause

之前,

Activity

已經失去了焦點,當進入

onStop

後,

Activity

的可見性最終變成了

View.GONE

Activity 銷毀時的列印

View與Activity之間不可不知的關系

這個就簡單明了,不用多說了

最後,附上

View

Activiy

關聯的生命周期流程圖:

View與Activity之間不可不知的關系