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?
Set the Adapter to RecyclerView on Fragment class This class will call the layout that consists of the RecyclerView and connect the adapter with the RecyclerView. onViewCreated() will set the RecyclerAdapter to the RecyclerView layout.
setLayoutManager(new LinearLayoutManager(this)); recyclerView. setAdapter(adapter); Just replace above code with this and it should work. What you did wrong is you called setAdapter(adapter) before calling layout manager.
According to the Android documentation, a fragment is a part of applications user interface that is bound to an activity. Fragments have their lifecycle and layouts or UI components. Fragments help enrich your UI design, pass data between different screens, and adapt to different device configurations.
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()
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; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With