Activity/ViewGroup/View生命周期方法

本文详细探讨了Android中Activity及自定义View的生命周期方法,包括onCreate、onStart等Activity生命周期,以及onMeasure、onLayout等View生命周期。通过实例演示了不同初始化方式下这些方法的调用顺序,为开发者理解Android视图的生命周期提供了实用指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Activity七个基本的生命周期方法:onCreate、onStart、onResume、onPause、onStop、onDestory,这六个生命周期方法两两相互对应,外加一个onRestart方法。
自定义View时,常需要复写的方法:onMeasure、onLayout、onDraw以及onSizeChanged、onFinishInflate。
so,这些方法放一起啥顺序?
先蛮测下呗,在MainActivity中给七个生命周期方法打log;自定义FrameLayout和TextView的子类,即CustomViewGroup和CustomView,仅仅给五个生命周期方法打log;这两个自定义View直接放到Activity的xml布局中:

1. 启动MainActitity

顺序MainActivityCustonViewGroupCustomView
1onCreate before setContentView
2CustonViewGroup(ctx, attrs)
3CustomView(ctx, attrs)
4onFinishInflate
5onFinishInflate
6onCreate after setContentView
7onStart
8onResume
9onMeasure
10onMeasure
11onMeasure
12onMeasure
13onMeasure
14onMeasure
15onMeasure
16onMeasure
17onSizeChanged
18onSizeChanged
19onLayout
20onLayout
21onMeasure
22onMeasure
23onMeasure
24onMeasure
25onLayout
26onLayout
27onDraw
28onDraw

2. 更改ViewGroup/View初始化方法

以上是通过直接布局到布局文件中在setContentView中,通过系统加载布局文件初始化。如果布局文件没有CustomViewGroup和CustomView,而是在setContentView方法后,通过代码方式new出CustomViewGroup/CustomView,然后通过add方式将CustomView对象添加到CustomViewGroup对象中,最后将CustomViewGroup添加到MainActivityb根布局中呢?

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.e(TAG, "onCreate: before setContentView");
        setContentView(R.layout.activity_main);
        Log.e(TAG, "onCreate: before addView");
        RelativeLayout root = (RelativeLayout) findViewById(R.id.activity_main);
        CustonViewGroup viewgroup = new CustonViewGroup(this);
        CustomView view = new CustomView(this);
        viewgroup.addView(view);
        root.addView(viewgroup);
        Log.e(TAG, "onCreate: after addView");
        Log.e(TAG, "onCreate: after setContentView");
    }
顺序MainActivityCustonViewGroupCustomView
1onCreate before setContentView
2onCreate before addView
3CustomViewGroup(ctx)
4CustomView(ctx)
5onCreate after addView
6onCreate after setContentView
7onStart
8onResume

以下同上面流程。

3. 总结1

通过布局方式添加控件,setContentView方法中,通过两个参数的构造方法初始化布局资源中所有的ViewGroup/View,并且回调了onFinishInflate方法。
同时也说明,onFinishInflate方法是在Activity的onCreate生命周期方法中调用的,但是如果是利用代码通过一个参数构造方法初始化ViewGroup/View此方法是没有被回调的。


public View(Context context){
    ...
}

public View(Context context, AttributeSet attrs){
    ...
}

protected void onFinishInflate() {
        ...
}

至于这个神奇的setContentView方法,可以参考
郭大神的Android LayoutInflater原理分析,带你一步步深入了解View(一)
鸿洋大神的鸿洋的 Android 源码解析 之 setContentView 一探究竟。

2. View的onMeasureonLayoutonDraw以及onSizeChanged方法是在Activity的onResume方法执行后调用的。这也说明为什么在onCreate方法中不能直接获取到View的宽高,全是0啊。至于如何获取?恩,百度一大堆了。
3. 至于为什么onMeasure这么厚颜无耻的重复调用,已经这些生命周期的调用坐等我搞懂。或者你们告诉我最好了。

4. 按下回退键

顺序MainActivityCustonViewGroupCustomView
1onPause
2onStop
3onDestroy

5. 重新进入MainActivity并按下Home键

顺序MainActivityCustonViewGroupCustomView
1onPause
2onStop

6.回到MainActivity

顺序MainActivityCustonViewGroupCustomView
1onRestart
2onStart
3onResume
4onDraw
5onDraw

7. ViewGroup父类方法:

这次我们在CustomViewGroup中多打几个log,看下ViewGroup对其子View生命周期方法的影响。

public class CustonViewGroup extends FrameLayout {
    public static final String TAG = CustonViewGroup.class.getSimpleName();
    //三个构造方法略

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.e(TAG, "onMeasure: before");
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.e(TAG, "onMeasure: after");
    }

    @Override
    protected void onLayout(boolean b, int e, int i1, int i2, int i3) {
        Log.e(TAG, "onLayout: before");
        super.onLayout(b, e, i1, i2, i3);
        Log.e(TAG, "onLayout: after");
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Log.e(TAG, "onDraw: before");
        super.onDraw(canvas);
        Log.e(TAG, "onDraw: after");
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        Log.e(TAG, "onSizeChanged: before");
        super.onSizeChanged(w, h, oldw, oldh);
        Log.e(TAG, "onSizeChanged: after");
    }

    @Override
    protected void onFinishInflate() {
        Log.e(TAG, "onFinishInflate: before");
        super.onFinishInflate();
        Log.e(TAG, "onFinishInflate: after");
    }
}

结果分析,流程基本跟第一次测试效果一样我们主要看CustomViewGroup和CustomView对应方法的顺序:

onFinishInflate
顺序CustonViewGroupCustomView
1onFinishInflate
2onFinishInflate before
3onFinishInflate after
onMeasure
顺序CustonViewGroupCustomView
1onMeasure before
2onMeasure
3onMeasure after
onSizeChanged和onLayout
顺序CustonViewGroupCustomView
1onSizeChanged before
2onSizeChanged after
3onLayout before
3onSizeChanged
3onLayout
3onLayout after
onDraw
顺序CustonViewGroupCustomView
1onDraw before
2onDraw after
3onDraw

8. 总结2

  1. ViewGroup的onFinishInflate、onSizeChanged、onDraw父类方法中没有调用子View的对应方法;
  2. ViewGroup的onMeasure父类方法中调用子View的对应方法;
  3. ViewGroup的onLayout父类方法中会调用子View的onSizeChanged和onLayout方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值