Android app NPE:无法在null对象上调用虚方法setOnClickListener

时间:2015-03-02 17:31:55

标签: java android android-fragments

我正在构建我的第一个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>

2 个答案:

答案 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的原因是您尝试访问的不同视图(ButtonTextView)不在您的活动的布局文件中,而是在您的片段和#39; s布局文件。

setContentView将布局文件中的所有视图添加到活动中。

要修复NPE,您需要在片段的Button中实例化视图(TextViewonCreateView),因为片段的布局文件包含您将要使用的所有视图。

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);
        }
    }
}

我希望这会有所帮助。