View的五个构造函数的区别

View的五个构造函数的区别_第1张图片
image.png
  1. View(),没有暴露出来,等于没有,过过过
     /**
     * Non-public constructor for use in testing
     */
    View() {
        mResources = null;
        mRenderNode = RenderNode.create(getClass().getName(), this);
    }

  1. View(Context context),当在代码中创建view时使用,传入一个上下文,使该View运行在其中,并且可以通过这个上下文获取主题、资源等。
    /**
     * Simple constructor to use when creating a view from code.
     *
     * @param context The Context the view is running in, through which it can
     *        access the current theme, resources, etc.
     */
    public View(Context context) {...}

  1. 从布局文件xml中填充出来的view使用这个2参的构造函数。
    第1个参数context上文说过了,第2个参数attr包含了在xml中定义的属性,初始化的时候需要把这些属性拿出来用。可以看到这个构造直接调用了一个三参构造。那么继续走
    /**
     * Constructor that is called when inflating a view from XML. This is called
     * when a view is being constructed from an XML file, supplying attributes
     * that were specified in the XML file. This version uses a default style of
     * 0, so the only attribute values applied are those in the Context's Theme
     * and the given AttributeSet.
     *
     * 

* The method onFinishInflate() will be called after all children have been * added. * * @param context The Context the view is running in, through which it can * access the current theme, resources, etc. * @param attrs The attributes of the XML tag that is inflating the view. * @see #View(Context, AttributeSet, int) */ public View(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); }


  1. 三参构造
    /**
     * Perform inflation from XML and apply a class-specific base style from a
     * theme attribute. This constructor of View allows subclasses to use their
     * own base style when they are inflating. For example, a Button class's
     * constructor would call this version of the super class constructor and
     * supply R.attr.buttonStyle for defStyleAttr; this
     * allows the theme's button style to modify all of the base view attributes
     * (in particular its background) as well as the Button class's attributes.
     *
     * @param context The Context the view is running in, through which it can
     *        access the current theme, resources, etc.
     * @param attrs The attributes of the XML tag that is inflating the view.
     * @param defStyleAttr An attribute in the current theme that contains a
     *        reference to a style resource that supplies default values for
     *        the view. Can be 0 to not look for defaults.
     * @see #View(Context, AttributeSet)
     */
    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

2参构造会调用这个3参构造,多了一个默认样式defStyleAttr,比如Button的构造会传一个Button的样式,然后调用了自己的四参构造

public Button(Context context, AttributeSet attrs) {
        this(context, attrs, com.android.internal.R.attr.buttonStyle);
}

而四参构造会调用父类TextView的四参构造,TextView会继续调用父类View的四参构造。

    public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

所以这个三参构造的第三个参数defStyleAttr是给View的子类传自己用的属性配置的。


  1. 四参构造
    /**
     * Perform inflation from XML and apply a class-specific base style from a
     * theme attribute or style resource. This constructor of View allows
     * subclasses to use their own base style when they are inflating.
     * 

* When determining the final value of a particular attribute, there are * four inputs that come into play: *

    *
  1. Any attribute values in the given AttributeSet. *
  2. The style resource specified in the AttributeSet (named "style"). *
  3. The default style specified by defStyleAttr. *
  4. The default style specified by defStyleRes. *
  5. The base values in this theme. *
*

* Each of these inputs is considered in-order, with the first listed taking * precedence over the following ones. In other words, if in the * AttributeSet you have supplied <Button * textColor="#ff000000"> * , then the button's text will always be black, regardless of * what is specified in any of the styles. * * @param context The Context the view is running in, through which it can * access the current theme, resources, etc. * @param attrs The attributes of the XML tag that is inflating the view. * @param defStyleAttr An attribute in the current theme that contains a * reference to a style resource that supplies default values for * the view. Can be 0 to not look for defaults. * @param defStyleRes A resource identifier of a style resource that * supplies default values for the view, used only if * defStyleAttr is 0 or can not be found in the theme. Can be 0 * to not look for defaults. * @see #View(Context, AttributeSet, int) */ public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { this(context); final TypedArray a = context.obtainStyledAttributes( attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes); ... }

比三参多了个defStyleRes,子类在覆写构造的时候可以传入样式资源到这里。可以看到,四参构造也是先调用了this(context),然后获取到TypeArray拿各种属性,再继续对view进行初始化操作。

总结:View(Context)是从代码中创建view走的构造。 View(Context,AttributeSet),是从xml中填充的view走的构造,2参会调用3参,3参调用4参,4参最后会调用1参,然后拿到所有属性再初始化。这样子类的构造可以传入特定的attr和style来初始化。

你可能感兴趣的:(View的五个构造函数的区别)