I'm building my first Android app (basic calculator) which consists of one Activity and a single fragment. The layout of the app (display and buttons) are defined in the fragment xml fragment_main.xml
and should be inflated on startup. However, the app immediately crashed with a NPE. I'm confused as to whether I should set the click listeners for the calculator buttons in the Activity's onCreate()
method, or in the fragment class's onCreateView()
method. Code and stack trace below.
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.github.idclark.calculator/com.github.idclark.calculator.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setOnClickListener(android.view.View$OnClickListener)' on a null object reference
public class MainActivity extends ActionBarActivity implements OnClickListener {
private TextView mCalculatorDisplay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new CalculatorFragment())
.commit();
}
mCalculatorDisplay = (TextView) findViewById(R.id.textView);
findViewById(R.id.AC).setOnClickListener(this);
findViewById(R.id.plusminus).setOnClickListener(this);
findViewById(R.id.percent).setOnClickListener(this);
findViewById(R.id.nine).setOnClickListener(this);
findViewById(R.id.eight).setOnClickListener(this);
findViewById(R.id.seven).setOnClickListener(this);
findViewById(R.id.six).setOnClickListener(this);
findViewById(R.id.five).setOnClickListener(this);
findViewById(R.id.four).setOnClickListener(this);
findViewById(R.id.three).setOnClickListener(this);
findViewById(R.id.two).setOnClickListener(this);
findViewById(R.id.one).setOnClickListener(this);
findViewById(R.id.zero).setOnClickListener(this);
findViewById(R.id.div).setOnClickListener(this);
findViewById(R.id.mult).setOnClickListener(this);
findViewById(R.id.plus).setOnClickListener(this);
findViewById(R.id.minus).setOnClickListener(this);
findViewById(R.id.dec).setOnClickListener(this);
findViewById(R.id.equal).setOnClickListener(this);
}
@Override
public void onClick(View v) {
String buttonPressed = ((Button )v).getText().toString();
mCalculatorDisplay.setText(buttonPressed);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class CalculatorFragment extends Fragment {
public CalculatorFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
Activity_Main
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container"
android:layout_width="match_parent" android:layout_height="match_parent"
tools:context=".MainActivity" tools:ignore="MergeRootFrame" />
Fragment_Main
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity$PlaceholderFragment"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="0"
android:id="@+id/textView"
android:layout_alignEnd="@+id/textView"
android:textSize="65dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/AC"
android:id="@+id/AC"
android:layout_weight="0.25" />
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/plusminus"
android:id="@+id/plusminus"
android:layout_weight="0.25" />
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/percent"
android:id="@+id/percent"
android:layout_weight="0.25" />
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/div"
android:id="@+id/div"
android:layout_weight="0.25" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/nine"
android:id="@+id/nine"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/eight"
android:id="@+id/eight"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/seven"
android:id="@+id/seven"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:id="@+id/mult"
android:text="@string/mult"
android:layout_weight="0.25"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/six"
android:id="@+id/six"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/five"
android:id="@+id/five"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/four"
android:id="@+id/four"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/minus"
android:id="@+id/minus"
android:layout_weight="0.25"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/three"
android:id="@+id/three"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/two"
android:id="@+id/two"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/one"
android:id="@+id/one"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/plus"
android:id="@+id/plus"
android:layout_weight="0.25"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="0.5"
android:text="@string/zero"
android:id="@+id/zero" />
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/dec"
android:id="@+id/dec"
android:layout_weight="0.25"/>
<Button
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="@string/equal"
android:id="@+id/equal"
android:layout_weight="0.25"/>
</LinearLayout>