Riptyde4
Riptyde4

Reputation: 5480

Trying to implement tab layout, null object reference on findViewByID

As the title suggests, I'm trying to implement a tab layout.

I'm not sure if this is a proper way to do this (a big reason why I'm asking this question), but inside my fragments OnCreate, I run an AsyncTask that dynamically loads the ListView inside the fragment with the data from my JSON API -> This is working properly for the FIRST tab, but for the SECOND tab, I get the following error:

java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ListView.setAdapter(android.widget.ListAdapter)' on a null object reference

This error results from the following line of code:

ListView listView = (ListView) getView().findViewById(R.id.managed_event_list);

The list with this ID is defined under the XML for the ManagedEvent activity, but it seems that when it's trying to find the element by that ID, it does not find it and returns a null reference.

I'm speculating that this is because my 2nd tab is not selected by default so the view does not exist yet once the app is loaded? The behavior suggests that the activity is trying to load both of my lists immediately which is fine with me, but it seems that it can't get access to the list in my 2nd fragment...

If I comment out the code to load the 2nd tab's fragment's list from the API, then no error occurs, I can switch back and forth between tabs showing the first tab loaded and nothing in the second, but as soon as I try to load the data for the 2nd tab, null pointer exception.

I'm wondering what the solution for this is/proper way to do this... If you can help at all in any way, I'd really appreciate it. I've been looking through tutorials and documentation for hours and can't seem to find anything helpful.

This is my onCreateView from my 2nd tab's fragment:

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

    // Construct the data source
    mLoadTask = new EventLoadTask();
    mLoadTask.execute((Void) null);

    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_events, container, false);
}

EDIT:

For anyone stumbling upon this: The last line of the above block of code was my problem. I cloned my 2nd activity's files from my first one since they are so similar and forgot to refactor R.layout.fragment_events to R.layout.fragment_managed_events ... Also see Ahmed's answer, which is probably the better way to do this.

Here is some of the code from my AsyncTask inside of my 2nd Tab's fragment:

@Override
    protected void onPostExecute(final Boolean success) {
        mLoadTask = null;

        if (success) {
            Gson gson = new Gson();
            EventList events = gson.fromJson(mResponse, EventList.class);

            Log.w("Retrieved events", events.toString());

            // Create the adapter to convert the array to views
            final EventListAdapter adapter = new EventListAdapter(getActivity().getApplicationContext(),
                    events.getEvents());
            // Attach the adapter to a ListView
            ListView listView = (ListView) getView().findViewById(R.id.managed_events_list);
            listView.setAdapter(adapter);
            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { ...

Here is my 2nd tab's fragment's XML:

<FrameLayout 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"
tools:context=".ManagedEventsFragment">

<ListView
    android:id="@+id/managed_events_list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"/>

</FrameLayout>

If you need to see anything else please comment

Upvotes: 2

Views: 1702

Answers (1)

Ahmed Hegazy
Ahmed Hegazy

Reputation: 12615

The problem is that you are loading from the network before the ,fragment view is created and that results null in the getView() method. If you have one fragment you will not notice, but if you have multiple fragments this can arise.

You should do your network communication after the view is created not on the onCreate() method like onViewCreated() or onCreateView() callback.

Upvotes: 2

Related Questions