Android自定義View的構造函數

自定義View是Android中一個常見的需求,每一個自定義的View都須要實現三個基本的構造函數,而這三個構造函數又有兩種常見的寫法。android

第一種

每一個構造函數分別調用基類的構造函數,再調用一個公共的初始化方法作額外初始化。函數

public class MyView extends ListView {
    public MyView(Context context) {
        super(context);
        sharedConstructor();
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        sharedConstructor();
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        sharedConstructor();
    }
    
    private void sharedConstructor() {
        // Do some initialize work.
    }
}

第二種

級聯式調用,每個構造函數調用比它多一個參數的構造函數,最後一個構造函數調用基類的構造函數,最後在作一些額外的初始化工做。this

public class MyView extends ListView {
    public MyView(Context context) {
        this(context, null);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        
        // Other initialize work.
    }
}

那麼問題來了,咱們該使用哪種方式呢?spa

結論是:最好使用第一種,由於第二種方法在某些狀況下會有問題,好比你自定義的View繼承自ListView或者TextView的時候,ListView或者TextView內部的構造函數會有一個默認的defStyle, 第二種方法調用時defStyle會傳入0,這將覆蓋基類中默認的defStyle,進而致使一系列問題。以ListView爲例,看看它的構造函數。code

public ListView(Context context) {
        this(context, null);
    }

    public ListView(Context context, AttributeSet attrs) { this(context, attrs, com.android.internal.R.attr.listViewStyle); } public ListView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public ListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        // Other works.
    }

能夠看到ListView的第二個構造函數代碼中傳入了一個com.android.internal.R.attr.listViewStyle,使用第二種方法(級聯式)調用時,咱們傳入的是0,將會覆蓋這個默認值。可是第一種方法中調用了super(context, attrs); 進而調用了基類的 this(context, attrs, com.android.internal.R.attr.listViewStyle);就不會產生問題。blog

整理自StackOverflow上的問題,原文連接繼承

==three

相關文章
相關標籤/搜索