Java – Null pointer exception in the Recyclerview adapter

Null pointer exception in the Recyclerview adapter… here is a solution to the problem.

Null pointer exception in the Recyclerview adapter

I’ve been trying to implement a recycled View for my activity, but I keep getting NullPointerException. This is my first time making a recyclerview, so please let me know if I’m doing something wrong. I’ll tell you all my code and then tell you where the error is

My main XML layout (called activity_main.xml).

<android.support.v4.widget.DrawerLayout
                xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:card_view="http://schemas.android.com/apk/res-auto"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/drawer"
                android:fitsSystemWindows="true">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

<include
            android:id="@+id/tool_bar"
            layout="@layout/tool_bar">
        </include>

<android.support.v7.widget.RecyclerView
            android:id="@+id/main_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingRight="8dp"
            android:paddingLeft="8dp"
            android:paddingTop="8dp"/>

</LinearLayout>

<android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer"/>

</android.support.v4.widget.DrawerLayout>

My recyclerview line XML (called main_recycler_view_row.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.support.v7.widget.CardView
        android:id="@+id/main_card"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

<LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

<TextView
                android:id="@+id/period_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="24sp"
                android:textColor="@android:color/black"
                android:paddingTop="24dp"
                android:paddingLeft="16dp"
                android:paddingBottom="4dp"/>

<TextView
                android:id="@+id/period_subtitle"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:paddingLeft="16dp"
                android:paddingBottom="16dp"/>

</LinearLayout>

</android.support.v7.widget.CardView>

</LinearLayout>

My main activity

package maxbleggi.afstudentplanner;

import android.content.Intent;
import android.content.res.Configuration;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

import com.parse.GetCallback;
import com.parse.Parse;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.ParseUser;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity
{
     "MACROS" for user's class periods
    private final int PERIOD1 = 0;
    private final int PERIOD2 = 1;
    private final int PERIOD3 = 2;
    private final int PERIOD4 = 3;
    private final int PERIOD5 = 4;
    private final int PERIOD6 = 5;
    private final int PERIOD7 = 6;

 toolbar
    private Toolbar toolbar;

 nav drawer
    private DrawerLayout navDrawer;

 user's data
    private String[] userClasses = new String[10];

 list to fill Classroom class with
    private List<ClassroomClass> classrooms;

/*
    * on creation of activity
     */
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

 initialise and set toolbar as actionbar
        toolbar = (Toolbar) findViewById(R.id.tool_bar);
        setSupportActionBar(toolbar);

 initialize drawer layout
        navDrawer = (DrawerLayout) findViewById(R.id.drawer);
        NavigationView navView = (NavigationView) findViewById(R.id.navigation_view);

 initialize recycler view elements
        RecyclerView mainRecyclerView = (RecyclerView)findViewById(R.id.main_recycler_view);

 initialize layout manager for recycler view
        RecyclerView.LayoutManager mainLayoutManager = new LinearLayoutManager(this);

 adapter for recycler view
        RecyclerView.Adapter mainAdapter= new MainRecyclerAdapter(classrooms);;

 initialize nav bars
        initNavBars();

 initialize nav drawer
        initNavDrawer();

 initialize data for all classes
        initClassData();

 add layout manager to recycler view
        mainRecyclerView.setLayoutManager(mainLayoutManager);

 add adapter to recycler view
        mainRecyclerView.setAdapter(mainAdapter);

}

/*
    * initializes the class data for each class
    */
    public void initClassData()
    {
         check if a user is not cached
        ParseUser currentUser = ParseUser.getCurrentUser();
        if (currentUser == null)
        {
             prompt user to Register screen
            Intent intent = new Intent(MainActivity.this, RegisterActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
            startActivity(intent);
        }

 query database for user's classes
        final ParseQuery<ParseObject> query = ParseQuery.getQuery("StudentClasses");
        query.whereEqualTo("student_id", ParseUser.getCurrentUser());

query.getFirstInBackground(new GetCallback<ParseObject>()
        {
            @Override
            public void done(ParseObject parseObject, ParseException e)
            {
                if (parseObject == null)
                {
                     retrieved the object
                    userClasses[PERIOD1]= parseObject.getString("first_period");
                    userClasses[PERIOD2]= parseObject.getString("second_period");
                    userClasses[PERIOD3]= parseObject.getString("third_period");
                    userClasses[PERIOD4]= parseObject.getString("fourth_period");
                    userClasses[PERIOD5]= parseObject.getString("fifth_period");
                    userClasses[PERIOD6]= parseObject.getString("sixth_period");
                    userClasses[PERIOD7]= parseObject.getString("seventh_period");
                }
                else
                {
                     failed lookup. Do something here
                }
            }
        });

 fill all fields for class periods
        classrooms = new ArrayList<>();

 titles of classes to add to list
        String[] classTitles = {"First Period", "Second Period", "Third Period", "Fourth Period",
                "Fifth Period", "Sixth Period", "Seventh Period"};

 iterate over every period to add it to the list
        for (int i = 0; i <= PERIOD7; i++)
        {
             if period registered was "Nothing" don't add it to list
            if (!userClasses[i].equals("Nothing"))
            //{
                classrooms.add(new ClassroomClass(userClasses[i], classTitles[i], i + 1));
            //}
        }
    }

public void initNavDrawer()
    {
        navDrawer = (DrawerLayout) findViewById(R.id.drawer);

final NavigationView navView = (NavigationView) findViewById(R.id.navigation_view);

navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener()
        {
            @Override
            public boolean onNavigationItemSelected(MenuItem menuItem)
            {
                menuItem.setChecked(true);
                navDrawer.closeDrawers();
                return true;
            }
        });
    }

private void initNavBars()
    {
       if (toolbar != null)
       {
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            toolbar.setNavigationIcon(R.drawable.ic_menu_white);
            toolbar.setNavigationOnClickListener(new View.OnClickListener()
            {
                @Override
                public void onClick(View v)
                {
                    navDrawer.openDrawer(GravityCompat.START);
                }
            });
       }
    }
}

My Data Field Class

package maxbleggi.afstudentplanner;

/*
 * Define the characteristics that all classroom cards have in common
*/
public class ClassroomClass
{

String className;
    String classPeriod;
    int classNumber;

public ClassroomClass(String className, String classPeriod, int classNumber)
    {
        this.className = className;
        this.classPeriod = classPeriod;
        this.classNumber = classNumber;
    }

public String getClassName()
    {
        return className;
    }

public String getClassPeriod()
    {
        return classPeriod;
    }

public int getClassNumber()
    {
        return classNumber;
    }
}

Finally, my adapter

package maxbleggi.afstudentplanner;

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

import java.util.List;

public class MainRecyclerAdapter extends RecyclerView.Adapter<MainRecyclerAdapter.ViewHolder>
{
    private List<ClassroomClass> classrooms;

public static class ViewHolder extends RecyclerView.ViewHolder
    {
         hold data items
        public View view;

ViewHolder(View itemView)
        {
            super(itemView);
            view = itemView;
        }
    }

public MainRecyclerAdapter(List<ClassroomClass> classrooms)
    {
        this.classrooms = classrooms;
    }

@Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i)
    {
         create a new view
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.main_recycler_view_row, viewGroup, false);

 set the view's parameters
        ViewHolder pvh = new ViewHolder(v);
        return pvh;
    }

@Override
    public void onBindViewHolder(ViewHolder viewHolder, int position)
    {
         get elements from view
        TextView title = (TextView) viewHolder.view.findViewById(R.id.period_title);
        TextView subtitle = (TextView) viewHolder.view.findViewById(R.id.period_subtitle);

 retrieve data from data field and put in view
        title.setText(classrooms.get(position).getClassName());
        subtitle.setText(classrooms.get(position).classPeriod);

}

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

@Override
    public void onAttachedToRecyclerView(RecyclerView recyclerView)
    {
        super.onAttachedToRecyclerView(recyclerView);
    }
}

When getting the item count here, I get java.lang.NullPointerException in my MainRecyclerAdapter

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

Thanks for any help or comments, thanks for all the code. I just want to make sure I’m thorough.

Solution

You must initialize the classroom data before creating the constructor, so just call

initClassData();

Before the adapter constructor.

By the way, you should execute this code in the viewholder constructor

// get elements from view
        TextView title = (TextView) viewHolder.view.findViewById(R.id.period_title);
        TextView subtitle = (TextView) viewHolder.view.findViewById(R.id.period_subtitle);

Then use it like this

holder.title.setText

holder.subtitle.setText

Related Problems and Solutions