Ray Lee
Ray Lee

Reputation: 13

Android RecyclerView adapter with fragment null pointer exception

Hi I am new to Android and get a problem with Recycler View and fragment. There are 3 fragments that can swipe, and there is a recycler view with an adapter that is in the fragment. I got a sample code from http://developer.android.com/training/implementing-navigation/lateral.html but I get null pointer exception in List object. Thanks in advance. My code is showed below:

public class TripHistoryActivity extends FragmentActivity implements ActionBar.TabListener{
private static final String TAG = "TripHistoryActivity";
private CommonDBHelper commonDBHelper;

private List<Trip> allTrips;
private ArrayList<Trip> currentTrips;
private ArrayList<Trip> pastTrips;
private ArrayList<Trip> futureTrips;

AppSectionsPagerAdapter mAppSectionsPagerAdapter;

ViewPager mViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_trip_history);
    commonDBHelper = new CommonDBHelper(this);
    TripDBHelper tripDBHelper = new TripDBHelper(commonDBHelper.getWritableDatabase());

    allTrips = tripDBHelper.getAllTrips();
    currentTrips = new ArrayList<>();
    pastTrips = new ArrayList<>();
    futureTrips = new ArrayList<>();
    Calendar calendar = Calendar.getInstance();
    int currentDay = calendar.get(calendar.DAY_OF_MONTH);
    int currentMonth = calendar.get(calendar.MONTH);
    int currentYear = calendar.get(calendar.YEAR);
    for (Trip trip : allTrips) {

        String date = trip.getTime().substring(0, trip.getTime().indexOf(" "));
        String[] dates = date.split("/");
        if (currentYear < Integer.valueOf(dates[2])) {
            futureTrips.add(trip);
        }
        else if (currentYear > Integer.valueOf(dates[2])
                || currentMonth > Integer.valueOf(dates[0])
                || currentDay > Integer.valueOf(dates[1])) {
            pastTrips.add(trip);
        }
        else {
            currentTrips.add(trip);
        }
    }

    mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager());
    final ActionBar actionBar = getActionBar();
    actionBar.setHomeButtonEnabled(false);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    mViewPager = (ViewPager) findViewById(R.id.pager);
    mViewPager.setAdapter(mAppSectionsPagerAdapter);
    mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
        @Override
        public void onPageSelected(int position) {
            // When swiping between different app sections, select the corresponding tab.
            // We can also use ActionBar.Tab#select() to do this if we have a reference to the
            // Tab.
            actionBar.setSelectedNavigationItem(position);
        }
    });

    for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) {
        // Create a tab with text corresponding to the page title defined by the adapter.
        // Also specify this Activity object, which implements the TabListener interface, as the
        // listener for when this tab is selected.
        actionBar.addTab(
                actionBar.newTab()
                        .setText(mAppSectionsPagerAdapter.getPageTitle(i))
                        .setTabListener(this));
    }
}


@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
    // When the given tab is selected, switch to the corresponding page in the ViewPager.
    mViewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}

/**
 * A {@link FragmentPagerAdapter} that returns a fragment corresponding to one of the primary
 * sections of the app.
 */
public class AppSectionsPagerAdapter extends FragmentPagerAdapter {

    public AppSectionsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public android.support.v4.app.Fragment getItem(int i) {
        switch (i) {
            case 0:
                android.support.v4.app.Fragment currentTripsFragment = new CurrentTripsFragment();
                Bundle currentTripsBundle = new Bundle();
                currentTripsBundle.putParcelableArrayList("currentTrips", currentTrips);
                currentTripsFragment.setArguments(currentTripsBundle);
                return currentTripsFragment;

            case 1:
                android.support.v4.app.Fragment pastTripsFragment = new PastTripsFragment();
                Bundle pastTripsBundle = new Bundle();
                pastTripsBundle.putParcelableArrayList("pastTrips", pastTrips);
                pastTripsFragment.setArguments(pastTripsBundle);
                return pastTripsFragment;

            default:
                android.support.v4.app.Fragment futureTripsFragment = new FutureTripsFragment();
                Bundle futureTripsBundle = new Bundle();
                futureTripsBundle.putParcelableArrayList("futureTrips", futureTrips);
                futureTripsFragment.setArguments(futureTripsBundle);
                return futureTripsFragment;
        }
    }

    @Override
    public int getCount() {
        return 3;
    }

    @Override
    public CharSequence getPageTitle(int position) {
        switch (position) {
            case 0:
                return "Current Trips";
            case 1:
                return "Past Trips";
            case 2:
                return "Future Trips";
            default:
                return "Fault";
        }
    }
}

/**
 * A fragment that launches other parts of the demo application.
 */
public static class CurrentTripsFragment extends android.support.v4.app.Fragment {
    private RecyclerView mRecyclerView;
    private Context context;
    List<Trip> currentTrips;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_current_trips, container, false);
        context = rootView.getContext();
        mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);

        currentTrips = getArguments().getParcelableArrayList("currentTrips");
        Log.d(TripHistoryActivity.TAG, String.valueOf(currentTrips == null));

        RecyclerView.LayoutManager manager = new LinearLayoutManager(context);
        mRecyclerView.setLayoutManager(manager);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);
        mRecyclerView.setAdapter(cardViewAdapter);
        cardViewAdapter.setOnItemClick(new CardViewAdapter.OnItemClick() {
            @Override
            public void onItemClick(int position) {
                handleItemClick(position);
            }
        });

        return rootView;
    }

    public void handleItemClick (int position) {
        Toast.makeText(context, "Clicked " + position, Toast.LENGTH_SHORT).show();
        Intent intent = new Intent(context, ViewTripActivity.class);
        intent.putExtra("trip", currentTrips.get(position));
        startActivity(intent);
    }
}

There are 2 other fragments that are same as this one so I omit them.

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.nyu.cs9033.eta.R;
import com.nyu.cs9033.eta.models.Trip;

import java.util.List;

/**
 * Created by Ray on 2016/4/2.
 */
public class CardViewAdapter extends RecyclerView.Adapter<CardViewAdapter.CardViewHolder> {
    private final List<Trip> trips;

    public CardViewAdapter (List<Trip> trips) {
        this.trips = trips;
    }

    public interface OnItemClick {
        public void onItemClick(int position);
    }

    private OnItemClick onItemClick;

    public void setOnItemClick (OnItemClick onItemClick) {
        this.onItemClick = onItemClick;
    }

    @Override
    public CardViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.history_list_item, parent, false);
        return new CardViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final CardViewHolder holder, final int position) {
        holder.name.setText(trips.get(position).getName());
        holder.location.setText(trips.get(position).getLocation());
        holder.time.setText(trips.get(position).getTime());
        if (onItemClick != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onItemClick.onItemClick(position);
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return trips.size();
    }

    class CardViewHolder extends RecyclerView.ViewHolder {
        private TextView name;
        private TextView location;
        private TextView time;

        public CardViewHolder (View view) {
            super(view);
            name = (TextView) view.findViewById(R.id.card_trip_name);
            location = (TextView) view.findViewById(R.id.card_trip_location);
            time = (TextView) view.findViewById(R.id.card_trip_time);
        }
    }

}

This is what logcat says:

FATAL EXCEPTION: mainProcess: com.nyu.cs9033.eta, PID: 14018
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()'
on a null object reference
at com.nyu.cs9033.eta.adapters.CardViewAdapter.getItemCount(CardViewAdapter.java: 57)
at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java: 2357)
at android.view.View.measure(View.java: 18796)
at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java: 715)
at android.widget.RelativeLayout.onMeasure(RelativeLayout.java: 461)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java: 194)
at android.view.View.measure(View.java: 18796)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java: 1488)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java: 194)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java: 446)
at android.view.View.measure(View.java: 18796)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java: 5951)
at android.widget.FrameLayout.onMeasure(FrameLayout.java: 194)
at com.android.internal.policy.PhoneWindow$DecorView.onMeasure(PhoneWindow.java: 2643)
at android.view.View.measure(View.java: 18796)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java: 2108)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java: 1224)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java: 1460)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java: 1115)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java: 6023)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java: 858)
at android.view.Choreographer.doCallbacks(Choreographer.java: 670)
at android.view.Choreographer.doFrame(Choreographer.java: 606)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java: 844)
at android.os.Handler.handleCallback(Handler.java: 739)
at android.os.Handler.dispatchMessage(Handler.java: 95)
at android.os.Looper.loop(Looper.java: 148)
at android.app.ActivityThread.main(ActivityThread.java: 5422)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 616)

Upvotes: 1

Views: 2057

Answers (2)

Chintan Soni
Chintan Soni

Reputation: 25267

You should get bundle from onCreate() instead of onCreateView(). Try the below change in your Fragment class:

public static class CurrentTripsFragment extends android.support.v4.app.Fragment {

private RecyclerView mRecyclerView;
private Context context;
List<Trip> currentTrips;

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

    if(getArguments()!= null){
        currentTrips = getArguments().getParcelableArrayList("currentTrips");
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_current_trips, container, false);
    context = rootView.getContext();
    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);

    Log.d(TripHistoryActivity.TAG, String.valueOf(currentTrips == null));

    RecyclerView.LayoutManager manager = new LinearLayoutManager(context);
    mRecyclerView.setLayoutManager(manager);
    mRecyclerView.setItemAnimator(new DefaultItemAnimator());
    CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);
    mRecyclerView.setAdapter(cardViewAdapter);
    cardViewAdapter.setOnItemClick(new CardViewAdapter.OnItemClick() {
        @Override
        public void onItemClick(int position) {
            handleItemClick(position);
        }
    });

    return rootView;
}

public void handleItemClick (int position) {
    Toast.makeText(context, "Clicked " + position, Toast.LENGTH_SHORT).show();
    Intent intent = new Intent(context, ViewTripActivity.class);
    intent.putExtra("trip", currentTrips.get(position));
    startActivity(intent);
}
}

Upvotes: 1

Chordin4tion
Chordin4tion

Reputation: 984

You are getting a null pointer exception on your list which you are using to show list items in recycler view...please check whether you are getting your data in the list or not...problem seems to be here:

CardViewAdapter cardViewAdapter = new CardViewAdapter(currentTrips);

and here:

currentTrips = getArguments().getParcelableArrayList("currentTrips");

Upvotes: 0

Related Questions