Display a RecyclerView in Fragment

fredthemugwump picture fredthemugwump · Oct 29, 2014 · Viewed 183.9k times · Source

I'm trying out the new RecyclerView in Android Lollipop and I'm stuck.

I'm trying to receive a list, with an icon and a TextView to the right of the icon, inside a Fragment.

I found this great tutorial on how to set up a RecyclerView. I have followed every point and only changed the item_layout.xml to fit my needs.

The project builds without any errors but when it launches on my device I'm getting this error:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.fredrikaldgard.materialcolors/com.fredrikaldgard.materialcolors.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' on a null object reference

I've tried to google the problem but I'm quite an amateur with Android development.

Here's my MainActivity:

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

    // 1. get a reference to recyclerView
    RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);

    // 2. set layoutManger
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    // this is data fro recycler view
    ItemData itemsData[] = { new ItemData("Indigo",R.drawable.circle),
            new ItemData("Red",R.drawable.color_ic_launcher),
            new ItemData("Blue",R.drawable.indigo),
            new ItemData("Green",R.drawable.circle),
            new ItemData("Amber",R.drawable.color_ic_launcher),
            new ItemData("Deep Orange",R.drawable.indigo)};


    // 3. create an adapter
    MyAdapter mAdapter = new MyAdapter(itemsData);
    // 4. set adapter
    recyclerView.setAdapter(mAdapter);
    // 5. set item animator to DefaultAnimator
    recyclerView.setItemAnimator(new DefaultItemAnimator());

And my MyAdapter:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ItemData[] itemsData;

public MyAdapter(ItemData[] itemsData) {
    this.itemsData = itemsData;
}

// Create new views (invoked by the layout manager)
@Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                               int viewType) {
    // create a new view
    View itemLayoutView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.item_layout, null);

    // create ViewHolder

    ViewHolder viewHolder = new ViewHolder(itemLayoutView);
    return viewHolder;
}

// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {

    // - get data from your itemsData at this position
    // - replace the contents of the view with that itemsData

    viewHolder.txtViewTitle.setText(itemsData[position].getTitle());
    viewHolder.imgViewIcon.setImageResource(itemsData[position].getImageUrl());


}

// inner class to hold a reference to each item of RecyclerView
public static class ViewHolder extends RecyclerView.ViewHolder {

    public TextView txtViewTitle;
    public ImageView imgViewIcon;

    public ViewHolder(View itemLayoutView) {
        super(itemLayoutView);
        txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
        imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
    }
}


// Return the size of your itemsData (invoked by the layout manager)
@Override
public int getItemCount() {
    return itemsData.length;
}
}

Edit: Here's the Fragment

public class ColorsFragment extends Fragment {

    public ColorsFragment(){}

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

        View rootView = inflater.inflate(R.layout.fragment_colors, container, false);

        return rootView;
    }
}

What has possibly gone wrong?

Answer

The Dude picture The Dude · Jun 28, 2015

This was asked some time ago now, but based on the answer that @nacho_zona3 provided, and previous experience with fragments, the issue is that the views have not been created by the time you are trying to find them with the findViewById() method in onCreate() to fix this, move the following code:

// 1. get a reference to recyclerView
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);

// 2. set layoutManger
recyclerView.setLayoutManager(new LinearLayoutManager(this));

// this is data fro recycler view
ItemData itemsData[] = { new ItemData("Indigo",R.drawable.circle),
        new ItemData("Red",R.drawable.color_ic_launcher),
        new ItemData("Blue",R.drawable.indigo),
        new ItemData("Green",R.drawable.circle),
        new ItemData("Amber",R.drawable.color_ic_launcher),
        new ItemData("Deep Orange",R.drawable.indigo)};


// 3. create an adapter
MyAdapter mAdapter = new MyAdapter(itemsData);
// 4. set adapter
recyclerView.setAdapter(mAdapter);
// 5. set item animator to DefaultAnimator
recyclerView.setItemAnimator(new DefaultItemAnimator()); 

to your fragment's onCreateView() call. A small amount of refactoring is required because all variables and methods called from this method have to be static. The final code should look like:

 public class ColorsFragment extends Fragment {

     public ColorsFragment() {}

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

         View rootView = inflater.inflate(R.layout.fragment_colors, container, false);
         // 1. get a reference to recyclerView
         RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.list);

         // 2. set layoutManger
         recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));

         // this is data fro recycler view
         ItemData itemsData[] = {
             new ItemData("Indigo", R.drawable.circle),
                 new ItemData("Red", R.drawable.color_ic_launcher),
                 new ItemData("Blue", R.drawable.indigo),
                 new ItemData("Green", R.drawable.circle),
                 new ItemData("Amber", R.drawable.color_ic_launcher),
                 new ItemData("Deep Orange", R.drawable.indigo)
         };


         // 3. create an adapter
         MyAdapter mAdapter = new MyAdapter(itemsData);
         // 4. set adapter
         recyclerView.setAdapter(mAdapter);
         // 5. set item animator to DefaultAnimator
         recyclerView.setItemAnimator(new DefaultItemAnimator());

         return rootView;
     }
 }

So the main thing here is that anywhere you call findViewById() you will need to use rootView.findViewById()