Android 自定義View構造方法初始化

現在發現又兩種方式:

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

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.
  }
}

第二種:

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

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.
  }
}

那麼問題來了,我們應該使用哪一種方式來進行初始化呢?

答案是:第一種

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

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);就不會產生問題。


發佈了104 篇原創文章 · 獲贊 138 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章