Display a RecyclerView in Fragment

198,902

Solution 1

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 from 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 from 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()

Solution 2

You should retrieve RecyclerView in a Fragment after inflating core View using that View. Perhaps it can't find your recycler because it's not part of Activity

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    final View view = inflater.inflate(R.layout.fragment_artist_tracks, container, false);
    final FragmentActivity c = getActivity();
    final RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
    LinearLayoutManager layoutManager = new LinearLayoutManager(c);
    recyclerView.setLayoutManager(layoutManager);

    new Thread(new Runnable() {
        @Override
        public void run() {
            final RecyclerAdapter adapter = new RecyclerAdapter(c);
            c.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    recyclerView.setAdapter(adapter);
                }
            });
        }
    }).start();

    return view;
}
Share:
198,902
fredthemugwump
Author by

fredthemugwump

Updated on June 28, 2021

Comments

  • fredthemugwump
    fredthemugwump almost 3 years

    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?

  • fredthemugwump
    fredthemugwump over 9 years
    Thanks a lot! I tried to replace my code inside my Fragment with yours but I got a problem with "final FragmentActivity c = getActivity();" It gives me an error: Required "android.support.v4.app.FragmentActitvity" Found "android.app.Activity". I have compiled the v4 support library in my project.
  • user4182277
    user4182277 over 9 years
    You can use any activity, you don't have to use support library if don't need it
  • fredthemugwump
    fredthemugwump over 9 years
    What do you mean by "use any activity"? I'm using the support library for a nav drawer anyway.
  • user4182277
    user4182277 over 9 years
    I meant any subclass of activity class. Sorry for not making it clear.
  • fredthemugwump
    fredthemugwump over 9 years
    I have to apologize, I'm not very good at complicated things like Fragments. What exactly should I write instead of "final FragmentActivity c = getActivity();"? When I replac FragmentActivity with just Activity the error disappears but I still have this error: imgur.com/amSWNWc
  • Dionysios Arvanitis
    Dionysios Arvanitis about 9 years
    mLayoutManager = new LinearLayoutManager(getActivity());
  • swapyonubuntu
    swapyonubuntu over 8 years
    replace this with getActivity() .
  • pcodex
    pcodex about 6 years
    You could also return the recyclerview from the fragment 'onCreateView' because essentially the fragment is now a RecyclerView
  • Pointyhat
    Pointyhat over 5 years
    may i ask why you setting the adapter in a runnable?
  • user4182277
    user4182277 over 5 years
    Adapter should be set on UI thread. Data is loaded on another thread and we can not interact with UI on non-ui thread. Please notice that using raw threads is usually bad practice. I think kotlin coroutines are new way to do so properly.
  • Learn2Code
    Learn2Code about 5 years
    Im getting an error with MyAdapter mAdapter = new MyAdapter(itemsData); it says MyAdapter(android.context.Context, List<>) in MyAdapter cannot be applied to (List<>)
  • clamum
    clamum over 4 years
    Thanks bruh. I'm just getting back into native Android development, after creating my first app years ago targeting v2.3.3, and yeah... let's just say a thing or two has changed. OH LAWD