I have been trying to find the cause of weird formatting style inconsistencies for my Views
throughout my application and I think I have narrowed it down with this example.
I set up two equivalent layouts of various Views
s with exactly the same procedure and only varying the Context
supplied in creation. In the first set, each View
is created with the application's context through Activity.getApplicationContext()
, whereas in the second set the View
s are fed the activity's context through this
.
The result is vastly different:
Any suggestions on why using the application context causes the garbage (and inconsistent - colours are white as well as grey) formatting seen in the screenshot?
Activity code:
import android.os.Bundle;
import android.app.Activity;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TextViews
TextView tv1 = new TextView(getApplicationContext());
tv1.setText("With Application context");
TextView tv2 = new TextView(this);
tv2.setText("With Activity context");
// Spinners
Spinner sp1 = new Spinner(getApplicationContext());
sp1.setAdapter(new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_spinner_item, new String[] {"App context 1", "App context 2", "App context 3"}));
Spinner sp2 = new Spinner(this);
sp2.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, new String[] {"Act context 1", "Act context 2", "Act context 3"}));
// Edittexts
EditText et1 = new EditText(getApplicationContext());
et1.setText("Application Context");
EditText et2 = new EditText(this);
et2.setText("Activity Context");
// Buttons
Button b1 = new Button(getApplicationContext());
b1.setText("Application Context");
Button b2 = new Button(this);
b2.setText("Activity Context");
// Layout structure
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.VERTICAL);
ll.addView(tv1);
ll.addView(sp1);
ll.addView(et1);
ll.addView(b1);
ll.addView(tv2);
ll.addView(sp2);
ll.addView(et2);
ll.addView(b2);
setContentView(ll);
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light" >
<activity
android:name="com.test.test.MainActivity"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo.Light" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
In Android sources getApplicationContext()
returns Application object which extends ContextWrapper
, so using getApplicationContext()
you are passing ContextWrapper
subclass, but when you pass this
, you are passing an Activity
object which extends ContextThemeWrapper
so you are passing ContextThemeWrapper
subclass. Now the difference between ContextWrapper
and ContextThemeWrapper
is that ContextWrapper
simply delegates all of its calls to another Context and ContextThemeWrapper
allows you to modify the theme from what is in the wrapped context.
Although, the question was more about why exactly this is happening (as opposed to the cause which was clear), here are also some helpful posts which explain the perils of incorrectly using application context and how to choose a context correctly:
Most importantly from @CommonsWare: "getApplicationContext() is not a complete Context and consequently does not support everything that Activity does."
Awesome post about Context that should clarify everything:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With