2014-11-03 70 views
1

我一直在通過本書專業的Android 4應用程序開發工作,並且陷入了其中一個教程。我的應用程序編譯得很好,但是當我運行它時,它崩潰並出現錯誤NullPointerException:嘗試調用虛方法'布爾java.util.ArrayList.add(null對象引用上的java.lang.Object'。這發生在我輸入文本時到Android的空指針異常 - 碎片(PA4AD)

的EditText上並回車,程序將出現在onNewItemAdded方法崩潰,在todoItems.add線。據我所知,我的ArrayList是正確初始化。

我relativly新到Java以及Android開發,我堅持認爲出了什麼問題。

對於那些不熟悉本書的應用程序,該應用程序包含一個編輯文本片段和一個列表片段

感謝您的幫助。

ToDoListActivity.java

import android.app.Activity; 
import android.app.FragmentManager; 
import android.os.Bundle; 
import android.view.Menu; 
import android.view.MenuItem; 
import android.widget.ArrayAdapter; 
import java.util.ArrayList; 


public class ToDoListActivity extends Activity 
    implements NewItemFragment.OnNewItemAddedListener { 

    private ArrayAdapter<String> aa; 
    private ArrayList<String> todoItems; 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // Inflate your View 
     setContentView(R.layout.main); 

     // Get references to UI widgets 
     FragmentManager fm = getFragmentManager(); 
     ToDoListFragment toDoListFragment = 
       (ToDoListFragment)fm.findFragmentById(R.id.ToDoListFragment); 

     // Create the Array List of to do items 
     final ArrayList<String> todoItems = new ArrayList<String>(); 

     // Create the Array Adapter to bind the array to the List View 
     final ArrayAdapter<String> aa; 

     aa = new ArrayAdapter<String>(this, 
       android.R.layout.simple_list_item_1, 
       todoItems); 

     // Bind the Array Adapter to the List View 
     toDoListFragment.setListAdapter(aa); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     // Handle action bar item clicks here. The action bar will 
     // automatically handle clicks on the Home/Up button, so long 
     // as you specify a parent activity in AndroidManifest.xml. 
     int id = item.getItemId(); 
     if (id == R.id.action_settings) { 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
    public void onNewItemAdded(String newItem) { 
     System.out.println(newItem); 
     todoItems.add(newItem); 
     aa.notifyDataSetChanged(); 
    } 
} 

NewItemFramgment.java

import android.app.Activity; 
import android.net.Uri; 
import android.os.Bundle; 
import android.app.Fragment; 
import android.view.KeyEvent; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.EditText; 


/** 
* A simple {@link Fragment} subclass. 
* Activities that contain this fragment must implement the 
* {@link NewItemFragment.OnNewItemAddedListener} interface 
* to handle interaction events. 
* 
*/ 
public class NewItemFragment extends Fragment { 

    private OnNewItemAddedListener onNewItemAddedListener; 

    public interface OnNewItemAddedListener { 
     public void onNewItemAdded(String newItem); 
    } 

    public NewItemFragment() { 
     // Required empty public constructor 
    } 


    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     View view = inflater.inflate(R.layout.new_item_fragment, container, false); 

     final EditText myEditText = (EditText)view.findViewById(R.id.myEditText); 

     myEditText.setOnKeyListener(new View.OnKeyListener() { 
      public boolean onKey(View v, int keyCode, KeyEvent event) { 
       if (event.getAction() == KeyEvent.ACTION_DOWN) 
       if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER) || 
         (keyCode == KeyEvent.KEYCODE_ENTER)) { 
        String newItem = myEditText.getText().toString(); 
        onNewItemAddedListener.onNewItemAdded(newItem); 
        myEditText.setText(""); 
        return true; 
       } 
      return false; 
     } 
    }); 

    return view; 
} 

/* // TODO: Rename method, update argument and hook method into UI event 
    public void onButtonPressed(Uri uri) { 
     if (mListener != null) { 
      mListener.onFragmentInteraction(uri); 
     } 
    }*/ 

    @Override 
    public void onAttach(Activity activity) { 
     super.onAttach(activity); 
     try { 
      onNewItemAddedListener = (OnNewItemAddedListener)activity; 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() 
        + " must implement OnItemAddedListener"); 
     } 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     onNewItemAddedListener = null; 
    } 
} 
+0

什麼是確切的錯誤信息你得到? – nem035 2014-11-03 20:46:37

+0

@nem logcat中的錯誤消息是:java.lang.NullPointerException:試圖調用虛擬方法'boolean java.util.ArrayList.add(java.lang.Class)對象)'在空對象引用 在com.example.todo.ToDoListActivity.onNewItemAdded(ToDoListActivity.java:63) – user288591 2014-11-03 20:50:02

回答

5

要了解你的問題,你需要了解如何在Java

總之variable scopes工作,你有類變量(也稱爲字段)和loc人變量:

class MyClass { 
    int myVar;  // Class Variable - this variable is visible to the whole class 

    void someMethod() { 
     int myVar; // Local Variable - this variable is visible only within someMethod() 
    } 
} 

通過使用相同的名稱既類和局部變量,裏面someMethod()變量是「hidding」全局類變量。

因此,你的問題是,你的onCreate裏面,你是重新聲明ArrayList稱爲todoItems說:

// Create the Array List of to do items 
final ArrayList<String> todoItems = new ArrayList<String>(); 

這意味着todoItems是指這個地方版本(僅onCreate內可見方法)而不是您在班級頂部定義的全局版本(對於您的整個班級可見)。

然而,你onNewItemAdded方法裏面,todoItems指從未被初始化的類全球ArrayList(並因此null),這就是爲什麼你得到一個NullPointerException

你應該改變上面的語句:

todoItems = new ArrayList<String>(); 

所以它指的是一流的全球ArrayList

注意:你有同樣的問題爲您ArrayAdapter<String> aa

+0

謝謝,它的工作現在,重要的是我明白爲什麼。 – user288591 2014-11-03 20:57:29

+0

@ user288591歡迎您:) – nem035 2014-11-03 20:58:05