我正在构建我的第一个Android应用程序(基本计算器),它由一个Activity和一个片段组成。应用程序的布局(显示和按钮)在片段xml fragment_main.xml
中定义,并且应该在启动时膨胀。然而,该应用程序立即与NPE崩溃。我是否应该在活动onCreate()
方法或片段类onCreateView()
方法中为计算器按钮设置点击监听器,这让我很困惑。代码和堆栈跟踪如下。
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>
答案 0 :(得分:1)
您应该覆盖Fragment
&#39; onViewCreated()
,因为可以保证所有View
都已实例化。
在CalculatorFragment
中创建一个字段,以存储要分配给按钮的OnClickListener
,您可以执行以下操作:
public static class CalculatorFragment extends Fragment {
OnClickListener mListener = null;
public CalculatorFragment(OnClickListener listener) {
mListener = listener;
}
//et cetera
在活动onCreate()
中,您必须在创建OnClickListener
时指定CalculatorFragment
:
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new CalculatorFragment(this))
.commit();
}
在覆盖onViewCreated()
中,使用getView()
获取View
返回的onCreateView()
,以便大多数来电变得像
getView().findViewById(R.id.the_id).setOnClickListener(this);
。
请参阅findViewById in fragment android,了解如何使用findViewById
答案 1 :(得分:1)
Null Pointer Exception的原因是您尝试访问的不同视图(Button
和TextView
)不在您的活动的布局文件中,而是在您的片段和#39; s布局文件。
setContentView将布局文件中的所有视图添加到活动中。
要修复NPE,您需要在片段的Button
中实例化视图(TextView
和onCreateView
),因为片段的布局文件包含您将要使用的所有视图。
public class MainActivity extends ActionBarActivity implements OnClickListener {
@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();
}
}
/**
* A placeholder fragment containing a simple view.
*/
public static class CalculatorFragment extends Fragment implements OnClickListener {
private TextView mCalculatorDisplay;
public CalculatorFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
mCalculatorDisplay = (TextView) rootView.findViewById(R.id.textView);
rootView.findViewById(R.id.AC).setOnClickListener(this);
rootView.findViewById(R.id.plusminus).setOnClickListener(this);
rootView.findViewById(R.id.percent).setOnClickListener(this);
rootView.findViewById(R.id.nine).setOnClickListener(this);
rootView.findViewById(R.id.eight).setOnClickListener(this);
rootView.findViewById(R.id.seven).setOnClickListener(this);
rootView.findViewById(R.id.six).setOnClickListener(this);
rootView.findViewById(R.id.five).setOnClickListener(this);
rootView.findViewById(R.id.four).setOnClickListener(this);
rootView.findViewById(R.id.three).setOnClickListener(this);
rootView.findViewById(R.id.two).setOnClickListener(this);
rootView.findViewById(R.id.one).setOnClickListener(this);
rootView.findViewById(R.id.zero).setOnClickListener(this);
rootView.findViewById(R.id.div).setOnClickListener(this);
rootView.findViewById(R.id.mult).setOnClickListener(this);
rootView.findViewById(R.id.plus).setOnClickListener(this);
rootView.findViewById(R.id.minus).setOnClickListener(this);
rootView.findViewById(R.id.dec).setOnClickListener(this);
rootView.findViewById(R.id.equal).setOnClickListener(this);
return rootView;
}
@Override
public void onClick(View v) {
String buttonPressed = ((Button )v).getText().toString();
mCalculatorDisplay.setText(buttonPressed);
}
}
}
我希望这会有所帮助。