简体   繁体   中英

Android ArrayList Null Pointer Exception when calling findViewById()

I am just about finished slamming my face into the wall with this one, so I have come to you for some assistance.

I am trying to populate a fragment with an ArrayList containing some grade data. The fragment will appear just fine so long as it is empty, but hooking up my ArrayAdapter to it causes a Null Pointer Exception. I believe the error is coming from trying to find my 'listViewGrades' view, but I do not know what to do about it. Below is my code as well as the stack trace:

GradeListFragment.java

public class GradeListFragment extends Fragment{

ArrayAdapter<String> gradeAdapter;
ListView lv;

@Override
public View onCreateView(   LayoutInflater inflater,
                            ViewGroup container,
                            Bundle savedInstanceState){

    Bundle grades = getActivity().getIntent().getExtras();
    ArrayList<String> gradeCategories = grades.getStringArrayList("grades");

    /* The error appears to be here */

    lv = (ListView)getView().findViewById(R.id.listViewGrades);
    gradeAdapter = new ArrayAdapter<String>(getActivity(),  R.layout.line_item, gradeCategories );
    lv.setAdapter(gradeAdapter); 

    return inflater.inflate(R.layout.gradelist_fragment, container, false);
}

GradeListActivity.java

public class GradeListActivity extends Activity{

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_gradelist);

    FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.gradelist_frag_container, new GradeListFragment());

    if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
        ft.add(R.id.detail_frag_container, new DetailFragment());
    }
    ft.commit();
}

activity_gradelist.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

 <FrameLayout
    android:id="@+id/gradelist_frag_container"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight= "1" />

gradelist_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ListView
    android:id="@+id/listViewGrades"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
</ListView>

MainActivity.java

public class MainActivity extends Activity {

Button showGrades;
GradeCollection grades;
TextView textViewNumericGrade;
TextView textViewLetterGrade;

double numericGrade;
String letterGrade;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    grades = new GradeCollection();

    GradeData e1 = new GradeData("exam", 1 ,80.00, "Exam 1");

    GradeData hw1 = new GradeData("homework", 1, 100.00, "Homework 1");
    GradeData hw2 = new GradeData("homework", 2, 10.00, "Homework 2");

    GradeData q1 = new GradeData("quiz", 1, 5.0, "Quiz 1");
    GradeData q2 = new GradeData("quiz", 2, 5.0, "Quiz 2");
    GradeData q3 = new GradeData("quiz", 3, 4.0, "Quiz 3");

    GradeData l1 = new GradeData("lab", 1, 1.0, "Lab 1");
    GradeData l2 = new GradeData("lab", 2, 1.0, "Lab 2");
    GradeData l3 = new GradeData("lab", 3, 1.0, "Lab 3");
    GradeData l4 = new GradeData("lab", 4, 1.0, "Lab 4");
    GradeData l5 = new GradeData("lab", 5, 1.0, "Lab 5");
    GradeData l6 = new GradeData("lab", 6, 0.0, "Lab 6");
    GradeData l7 = new GradeData("lab", 7, 0.0, "Lab 7");
    GradeData l8 = new GradeData("lab", 8, 1.0, "Lab 8");


    grades.addGrade(e1);
    grades.addGrade(hw1);
    grades.addGrade(hw2);
    grades.addGrade(q1);
    grades.addGrade(q2);
    grades.addGrade(q3);
    grades.addGrade(l1);
    grades.addGrade(l2);
    grades.addGrade(l3);
    grades.addGrade(l4);
    grades.addGrade(l5);
    grades.addGrade(l6);
    grades.addGrade(l7);
    grades.addGrade(l8);


    showGrades =  (Button)findViewById(R.id.buttonShowGrades);
    showGrades.setOnClickListener( new OnClickListener(){
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this, GradeListActivity.class);
            intent.putExtra("grades", grades);
            startActivity(intent);
            }
        });

}

activity_main.xml

<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:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >

<TextView
    android:id="@+id/textViewName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/name"
    android:textAppearance="?android:attr/textAppearanceMedium" />

<RatingBar
    android:id="@+id/ratingBarGrade"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:numStars="4"
    android:stepSize="1.0"
    android:rating="0"/>

<TextView
    android:id="@+id/textViewNumericGrade"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/numericGrade"
    android:textAppearance="?android:attr/textAppearanceMedium" />

<TextView
    android:id="@+id/textViewLetterGrade"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/letterGrade"
    android:textAppearance="?android:attr/textAppearanceMedium" />

<Button
    android:id="@+id/buttonShowGrades"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/buttonViewGrades" />

stack trace

03-30 18:02:41.138: E/AndroidRuntime(2288): FATAL EXCEPTION: main
03-30 18:02:41.138: E/AndroidRuntime(2288): Process: bcs421.michaelsheron.hwk.gradeapp.presentation, PID: 2288
03-30 18:02:41.138: E/AndroidRuntime(2288): java.lang.RuntimeException: Unable to start activity ComponentInfo{bcs421.michaelsheron.hwk.gradeapp.presentation/bcs421.michaelsheron.hwk.gradeapp.presentation.GradeListActivity}: java.lang.NullPointerException
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.ActivityThread.access$800(ActivityThread.java:135)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.os.Handler.dispatchMessage(Handler.java:102)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.os.Looper.loop(Looper.java:136)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.ActivityThread.main(ActivityThread.java:5017)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at java.lang.reflect.Method.invokeNative(Native Method)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at java.lang.reflect.Method.invoke(Method.java:515)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at dalvik.system.NativeStart.main(Native Method)
03-30 18:02:41.138: E/AndroidRuntime(2288): Caused by: java.lang.NullPointerException
03-30 18:02:41.138: E/AndroidRuntime(2288):     at bcs421.michaelsheron.hwk.gradeapp.presentation.GradeListFragment.onCreateView(GradeListFragment.java:26)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.Fragment.performCreateView(Fragment.java:1700)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:890)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.BackStackRecord.run(BackStackRecord.java:684)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1447)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.Activity.performStart(Activity.java:5240)
03-30 18:02:41.138: E/AndroidRuntime(2288):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2168)
03-30 18:02:41.138: E/AndroidRuntime(2288):     ... 11 more

I'd like to thank everyone in advance for taking the time to look this over, as well as apologize if there is something missing.

In your GradleListFragment.java in the method onCreateView() first you must declare the root view where all the ui components will be instantiated, then call the findViewById() method on the newly created view.

Turn your code into this and try if it works the way you need.

@Override
public View onCreateView(LayoutInflater inflater,
                         ViewGroup container,
                         Bundle savedInstanceState) {

    View root = inflater.inflate(R.layout.gradelist_fragment, container, false);

    Bundle grades = getActivity().getIntent().getExtras();
    ArrayList<String> gradeCategories = grades.getStringArrayList("grades");

    lv = (ListView)root.findViewById(R.id.listViewGrades);
    gradeAdapter = new ArrayAdapter<String>(getActivity(),  R.layout.line_item, gradeCategories );
    lv.setAdapter(gradeAdapter);

    return root;
}

The problem you have is you are trying to refer to an element in a view that does not exist yet. Android expects to find that component in a View and yet you are inflating the view after you actually have made a reference to it. Hence the reference resolves to null. Hence you are getting the NullPointerException. Instead, do the following to get resolve this error:

@Override
public View onCreateView(LayoutInflater inflater,
                            ViewGroup container,
                            Bundle savedInstanceState){

    Bundle grades = getActivity().getIntent().getExtras();
    ArrayList<String> gradeCategories = grades.getStringArrayList("grades");

    View view = inflater.inflate(R.layout.gradelist_fragment, container, false)

    lv = (ListView)view.findViewById(R.id.listViewGrades);
    gradeAdapter = new ArrayAdapter<String>(getActivity(),  R.layout.line_item, gradeCategories );
    lv.setAdapter(gradeAdapter); 

    return view;
}

A good design principle would be to make these references within the onViewCreated() method which gets called after the View is created and which point all the elements resolve to their expected values.

First of all, the answer from @Eric is absolutely correct, and you should keep the code that he suggested.

Since it looks like you're still having the original issue, I'll post this answer as well.

It looks like you should probably create a custom adapter in order to do what you're trying to do here.

I assume that you're trying to get all of the information in each GradeData object to display in each row in the ListView.

One issue I see is that you're passing a GradeCollection as an extra here:

GradeCollection grades;
//..........
intent.putExtra("grades", grades);
startActivity(intent);

and trying to retrieve it as a String ArrayList

ArrayList<String> gradeCategories = grades.getStringArrayList("grades");

I'm guessing that gradeCategories is null at this point, since a GradeCollection object is not a ArrayList<String> , so when you try to feed it to your ArrayAdapter here:

gradeAdapter = new ArrayAdapter<String>(getActivity(),  R.layout.line_item, gradeCategories );

That is probably where you get the Null Pointer Exception.

There are a few different ways to go about fixing this, and you will want to eventually create a custom adapter so that you can display data from your objects. Just to get you started though, try this:

public class MainActivity extends Activity {

Button showGrades;
//GradeCollection grades;
ArrayList<String> grades;
TextView textViewNumericGrade;
TextView textViewLetterGrade;

double numericGrade;
String letterGrade;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //grades = new GradeCollection();

    String e1 = "exam  1  80.00  Exam 1";

    //grades.addGrade(e1);
    grades.add(e1);

    showGrades =  (Button)findViewById(R.id.buttonShowGrades);
    showGrades.setOnClickListener( new OnClickListener(){
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(MainActivity.this, GradeListActivity.class);
            intent.putExtra("grades", grades);
            startActivity(intent);
            }
        });

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM