2012-02-08 19 views
10

カスタムビューを作成するときに、私は多くの人々がこのようにそれを行うように見えることに気づいた:これでandroidカスタムビューコンストラクタの場合はsuper()を呼び出すかthis()を呼び出す必要がありますか?

public MyView(Context context) { 
    super(context); 
    // this constructor used when programmatically creating view 
    doAdditionalConstructorWork(); 
} 

public MyView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    // this constructor used when creating view through XML 
    doAdditionalConstructorWork(); 
} 

private void doAdditionalConstructorWork() { 
    // init variables etc. 
} 

私の問題は、それが私の変数は、最終的な作りから私を停止することです。次のことをしない理由は何ですか?

public MyView(Context context) { 
    this(context, null); 
    // this constructor used when programmatically creating view 
} 

public MyView(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
    // this constructor used when creating view through XML 
} 

public MyView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    // this constructor used where? 
    // init variables 
} 

私は、XMLを通って、コードをうまくビューを作成することができましたが、私はこのアプローチにはどんな欠点があるかはわかりません。これはすべての場合に有効ですか?

another part to this question

+0

'this'を呼び出すと、現在のクラスの別のコンストラクタが呼び出されます。私はこれがあなたが気づいていないことだと思います。このように 'this(context、null);'は 'public MyView(Context context、AttributeSet attrs){'を呼び出し、 'public MyView(Context context、AttributeSet attrs、int defStyle){'このコンストラクタの呼び出しは、Java言語ではあまり一般的ではありませんが、これはうまくいかない理由はありません。 –

+0

私は、パラメータについて心配していました。 :) –

答えて

-5

OKです。

TextView.javaのソースを見ると、

これらは同じ階層を使用しています。

あなたはこのアプローチで大丈夫です。

+0

これを投票してもらう人は理由も述べてください。アンドロイド自身の実装リファレンスも追加しました。この回答は、OPの与えられたシナリオでは正しいです。 –

-2

はうん、それはあなたがいないがあなたのコンストラクタの一つ一つにカスタム作業を繰り返す必要があります使用するための合理的なパターンですがあります。そして、いいえ、このメソッドには何の欠点もないようです。

-2

これは純粋にあなたの要件に依存します。親ビューのメソッドをカスタムビューでオーバーライドせずに使用する場合は、super()を使用して親クラスをインスタンス化する必要があります。親クラスのメソッドを呼び出す必要がない場合は、すべての実装がカスタムビューでオーバーライドされます。これは必要ありません。 linkのカスタム表示例セクションを読んでください。

7

私が見ることができる(誰も言及していない)唯一の欠点は、2番目のコンストラクタがゼロに設定されているため、スーパークラスのdefStyleが失われることです。 AndroidのViewクラスのソースコードを見ると、2番目のコンストラクタには常にdefStyleが定義されていることがわかります。例えば、これは、リストビューの第二のコンストラクタ

されています:

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

あなたはあなたが記述第二のアプローチを使用してリストビューを拡張していた場合は、迂回することと思いますので、com.android.internal.R.attr.listViewStyleはもはや、defStyleないだろうその2番目のスーパーコンストラクタを作成し、その代わりにゼロにします。私はあなたがそうのように、リストビューと同じdefstyleを使用してこれを解決することができたとします

​​

しかし、あなたが人為的にListViewコントロールとしてdefStyle同じを持って、それを強制しているので、それは、まさに「純粋主義者」の方法ではありません。

他の人の意見に反して、私は実際にあなたの投稿に記載されている最初のdoAdditionalConstructorWork()アプローチを使う方が良いと思っています。これは少なくともdefStyleが正しく設定されているからです。

+0

しかし、 'View'ソースコードを見ると** ** defStyle'を0に設定していることがわかります。' public View(Context context、AttributeSet attrs){ this(context、attrs、0); } ' –

3

これは私の回答と同様の質問です。

3つのコンストラクタをすべてオーバーライドする場合は、CASCADE this(...)コールを使用しないでください。あなたは代わりにこれを実行する必要があります。

public MyView(Context context) { 
    super(context); 
    init(context, null, 0); 
} 

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

public MyView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    init(context, attrs, defStyle); 
} 

private void init(Context context, AttributeSet attrs, int defStyle) { 
    // do additional work 
} 

理由は、親クラスが誤って上書きされるかもしれないことを、自身のコンストラクタでデフォルト属性を含むかもしれないということです。たとえば、これはTextViewのコンストラクタです:

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

public TextView(Context context, @Nullable AttributeSet attrs) { 
    this(context, attrs, com.android.internal.R.attr.textViewStyle); 
} 

public TextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 
    this(context, attrs, defStyleAttr, 0); 
} 

あなたがsuper(context)を呼び出していない場合は、あなたが適切なスタイルattrのようR.attr.textViewStyleを設定していません。

関連する問題