View のコンストラクタは Context を必要とします。
Context として以下のように Application Context を渡しているコードを見かけました。
View に渡された Context はスタイル属性を取得するのに使われます。
View.java
このことを踏まえて obtainStyledAttributes() の中身をみると
Context.java
つまり、3. では Context が持っているテーマ情報を使っているのです。
Application Context を渡してはいけない理由がわかったでしょうか。
Activity ごとにテーマを指定できるのに、Application Context を渡してしまうと、Activity のテーマが全く利用されません。
実際にやってみましょう。
Application には Theme.AppCompat(黒系)、MainActivity には Theme.AppCompat.Light(白系)を指定します。
![]()
画面のテーマは Theme.AppCompat.Light (白系)なのに、Application Context を渡した上のボタンは Theme.AppCompat(黒系)の色になってしまっています。
Context が持つテーマが利用されるという仕組みは、v7 AppCompat Support Library でも使われています。 AppCompatTextView を見てみましょう。
これにより、colorAccent の指定色によって自動でテキストカーソルなどが tint されます。
Context として以下のように Application Context を渡しているコードを見かけました。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Button textView = new Button(getApplicationContext()); } }
これがなぜよくないのか説明します。 View に渡された Context はスタイル属性を取得するのに使われます。
View.java
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); ... background = a.getDrawable(attr); ...
View のスタイルは - 1. XMLタグで指定された値(例 android:background="@drawable/button_bg")
- 2. style で指定された値(例 style="@style/MyButtonStyle)
- 3. テーマで指定された値(例 テーマの中で
- @style/MyButtonStyle
)
このことを踏まえて obtainStyledAttributes() の中身をみると
Context.java
public final TypedArray obtainStyledAttributes( AttributeSet set, @StyleableRes int[] attrs, @AttrRes int defStyleAttr, @StyleRes int defStyleRes) { return getTheme().obtainStyledAttributes( set, attrs, defStyleAttr, defStyleRes); }
getTheme() で Theme を取得し、Theme の obtainStyledAttributes() を呼んでいます。つまり、3. では Context が持っているテーマ情報を使っているのです。
Application Context を渡してはいけない理由がわかったでしょうか。
Activity ごとにテーマを指定できるのに、Application Context を渡してしまうと、Activity のテーマが全く利用されません。
実際にやってみましょう。
Application には Theme.AppCompat(黒系)、MainActivity には Theme.AppCompat.Light(白系)を指定します。
<manifest ...> <application ... android:theme="@style/Theme.AppCompat"> <activity android:name=".MainActivity" android:theme="@style/Theme.AppCompat.Light"> ... </activity> </application> </manifest>
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button1 = new Button(getApplicationContext()); button1.setText("Application Context"); Button button2 = new Button(this); button1.setText("Activity Context"); LinearLayout ll = (LinearLayout) findViewById(R.id.container); ll.addView(button1); ll.addView(button2); } }

画面のテーマは Theme.AppCompat.Light (白系)なのに、Application Context を渡した上のボタンは Theme.AppCompat(黒系)の色になってしまっています。
Context が持つテーマが利用されるという仕組みは、v7 AppCompat Support Library でも使われています。 AppCompatTextView を見てみましょう。
public class AppCompatTextView extends TextView implements TintableBackgroundView { ... public AppCompatTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(TintContextWrapper.wrap(context), attrs, defStyleAttr);
TintContextWrapper でラップした Context を TextView に渡しています。これにより、colorAccent の指定色によって自動でテキストカーソルなどが tint されます。