1. What is RecyclerView?
In Android 5.0 Lollipop, Android introduced RecyclerView widget. RecyclerView is flexible and efficient version of ListView. It is an container for rendering larger data set of views that can be recycled and scrolled very efficiently. RecyclerView is like traditional ListView widget, but with more flexibility to customizes and optimized to work with larger datasets. It uses a subclass of RecyclerView.Adapter
for providing views that represent items in a data set.
Android SDK doesn’t includes the RecyclerView
class. You need to add the following support library graddle dependency to project build.graddle
file.
compile 'com.android.support:recyclerview-v7:24.0.0'
This guide explains how to use and customize RecyclerView in Android applications.
2. RecyclerView Example
In the course of this example we will download the data from JSON API, parse and display the items on RecyclerView. As you can notice in the following image, we will be using both RecyclerView and CardView for creating the App UI.
Following steps are required to complete the example:
- Create a new Android Application and add the required graddle dependencies
- Layout activity and add RecyclerView and ProgressBar
- Layout the RecyclerView row item using CardView widget
- Create a Custom Adapter for RecyclerView
- Create main Activity to initialize UI, make HTTP Server request and render data on RecyclerView
- Responding to RecyclerView click event
2.1. Creating Android Project
Let us begin with creating a new Android project in Android Studio. After the project is created, open app build.graddle
file and add the following dependency libraries.
dependencies { compile 'com.android.support:recyclerview-v7:24.0.0' compile 'com.android.support:cardview-v7:24.0.0' compile 'com.squareup.picasso:picasso:2.5.2' // ... }
Notice that, we have added RecyclerView, CardView support libraries and Picasso dependency module.
Picasso is an Open Source image loader library created and maintained by Square. It is among the powerful image download and caching library for Android.
Adding Internet Permission:
You might be aware that, Android application must declare all the permissions that are required for application. As we need to download the data form server, we need to add the INTERNET
permission. Declare the following permission in AndroidManifest.xml
file.
<uses-permission android:name="android.permission.INTERNET" />
2.2. Declaring Activity Layout
Let us now define the layout for Activity. We will add a RecyclerView and ProgressBar inside a RelativeLayout. The progress bar will be displayed while the data data from REST API is being downloaded.
Create a new file activity_main.xml
inside layout resource folder and paste the following snippets.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#f1f1f1" android:padding="12dp" tools:context="com.stacktips.recyclerview.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"/> <ProgressBar android:id="@+id/progress_bar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"/> </RelativeLayout>
2.3. RecyclerView Row Layout
In the example, each row item is represented by a CardView
that hosts a RelativeLayout with an ImageView
for the thumbnail and a TextView
title. This layout resides in the file list_row.xml.
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cardview="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="5dp" cardview:cardCornerRadius="2dp" cardview:cardElevation="3dp" cardview:cardUseCompatPadding="true"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:id="@+id/thumbnail" android:layout_width="match_parent" android:layout_height="180dp" android:layout_alignParentTop="true" android:scaleType="centerCrop" android:src="@drawable/placeholder"/> <TextView android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/thumbnail" android:layout_centerVertical="true" android:layout_marginLeft="12dp" android:maxLines="3" android:padding="8dp" android:textAppearance="@style/TextAppearance.AppCompat.Headline" android:textColor="#444" android:textSize="18dp" android:textStyle="bold"/> </RelativeLayout> </android.support.v7.widget.CardView>
2.4. Creating RecyclerView Adapter
Android RecyclerView includes special kind of adapter which works pretty much same as traditional Android adapters but with additional functionalities.It uses a subclass of RecyclerView.Adapter
for providing views that represent items in a data set.
The additional functionalities of RecyclerView.Adapter are:
- It adds two new methods like
onCreateViewHolder()
andonBindViewHolder()
to organize the code. You must override these two methods for inflate the view and to bind data to the view - Implements a ViewHolder by default. Conceptually
RecyclerView.ViewHolder
works same as the ViewHolder design pattern which we have been using with other Adapters - Takes care of the overhead of recycling and gives better performance and scrolling
Create a new class MyRecyclerViewAdapter.class and copy the following snippets.
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.CustomViewHolder> { private List<FeedItem> feedItemList; private Context mContext; public MyRecyclerViewAdapter(Context context, List<FeedItem> feedItemList) { this.feedItemList = feedItemList; this.mContext = context; } @Override public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null); CustomViewHolder viewHolder = new CustomViewHolder(view); return viewHolder; } @Override public void onBindViewHolder(CustomViewHolder customViewHolder, int i) { FeedItem feedItem = feedItemList.get(i); //Render image using Picasso library if (!TextUtils.isEmpty(feedItem.getThumbnail())) { Picasso.with(mContext).load(feedItem.getThumbnail()) .error(R.drawable.placeholder) .placeholder(R.drawable.placeholder) .into(customViewHolder.imageView); } //Setting text view title customViewHolder.textView.setText(Html.fromHtml(feedItem.getTitle())); } @Override public int getItemCount() { return (null != feedItemList ? feedItemList.size() : 0); } class CustomViewHolder extends RecyclerView.ViewHolder { protected ImageView imageView; protected TextView textView; public CustomViewHolder(View view) { super(view); this.imageView = (ImageView) view.findViewById(R.id.thumbnail); this.textView = (TextView) view.findViewById(R.id.title); } } }
Notice that we have created an private ViewHolder class. The ViewHolder class contains the reference to the each of the ui widget on the row.
The FeedItem
class is an model class that holds the parsed data retrieved from JSON API. Add a new new file FeedItem.java
class in your project source folder and add the following.
public class FeedItem { private String title; private String thumbnail; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getThumbnail() { return thumbnail; } public void setThumbnail(String thumbnail) { this.thumbnail = thumbnail; } }
2.5. Activity Using RecyclerView
The resulting RecyclerView implementation for this example app consists of MainActivity initialization code. MainActivity creates the mRecyclerView instance, download and parse the data from JSON API, instantiates the adapter and plugs in the adapter to RecyclerView.
The focus of this tutorial is narrow down to RecyclerView, hence it doesn’t include any explanation for download and parse data from server. For learning how to download data from server, you may read Android Networking Tutorial.
Once data is downloaded, inside onPostExecute()
we are initializing the adapter and setting adapter to RecyclerView instance by just calling setAdapter()
method.
public class MainActivity extends AppCompatActivity { private static final String TAG = "RecyclerViewExample"; private List<FeedItem> feedsList; private RecyclerView mRecyclerView; private MyRecyclerViewAdapter adapter; private ProgressBar progressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); progressBar = (ProgressBar) findViewById(R.id.progress_bar); String url = "http://stacktips.com/?json=get_category_posts&slug=news&count=30"; new DownloadTask().execute(url); } public class DownloadTask extends AsyncTask<String, Void, Integer> { @Override protected void onPreExecute() { progressBar.setVisibility(View.VISIBLE); } @Override protected Integer doInBackground(String... params) { Integer result = 0; HttpURLConnection urlConnection; try { URL url = new URL(params[0]); urlConnection = (HttpURLConnection) url.openConnection(); int statusCode = urlConnection.getResponseCode(); // 200 represents HTTP OK if (statusCode == 200) { BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); StringBuilder response = new StringBuilder(); String line; while ((line = r.readLine()) != null) { response.append(line); } parseResult(response.toString()); result = 1; // Successful } else { result = 0; //"Failed to fetch data!"; } } catch (Exception e) { Log.d(TAG, e.getLocalizedMessage()); } return result; //"Failed to fetch data!"; } @Override protected void onPostExecute(Integer result) { progressBar.setVisibility(View.GONE); if (result == 1) { adapter = new MyRecyclerViewAdapter(MainActivity.this, feedsList); mRecyclerView.setAdapter(adapter); } else { Toast.makeText(MainActivity.this, "Failed to fetch data!", Toast.LENGTH_SHORT).show(); } } } private void parseResult(String result) { try { JSONObject response = new JSONObject(result); JSONArray posts = response.optJSONArray("posts"); feedsList = new ArrayList<>(); for (int i = 0; i < posts.length(); i++) { JSONObject post = posts.optJSONObject(i); FeedItem item = new FeedItem(); item.setTitle(post.optString("title")); item.setThumbnail(post.optString("thumbnail")); feedsList.add(item); } } catch (JSONException e) { e.printStackTrace(); } } }
3. Handle RecyclerView Click Event
Handling click event on RecyclerView is not as sweet as handling click listener in ListView or GridView. Android RecyclerView doesn’t provide any built in listeners or handy way of handling click events.
Let us declare a interface that specifies listener’s behavior. When user clicks on the RecyclerView the listener will return the FeedItem for the selected row.
public interface OnItemClickListener { void onItemClick(FeedItem item); }
Now turn on to adapter and declare an instance variable of OnItemClickListener along with getter and setter methods.
private OnItemClickListener onItemClickListener; public OnItemClickListener getOnItemClickListener() { return onItemClickListener; } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; }
In activity class, let set the click listener to adapter by calling setOnItemClickListener() method.
adapter.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(FeedItem item) { Toast.makeText(MainActivity.this, item.getTitle(), Toast.LENGTH_LONG).show(); } });
Now, attach the View.OnClickListener to each of the view you want to handle click. Add the following snippet to onBindViewHolder of the RecyclerView.Adapter. When ImageView or TextView is clicked, we will receive the event back to the caller activity.
View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View v) { onItemClickListener.onItemClick(feedItem); } }; customViewHolder.imageView.setOnClickListener(listener); customViewHolder.textView.setOnClickListener(listener);
Hi,
Please look at this nice Tutorial also
https://raichand-java.blogspot.in/2017/12/createretrieveupdate-and-delete-row-in.html
Thanks
Raichand
Hi Nilanchala, I had just starting on programming and still learning a lot regarding java classes and etc. Right now I has already make an application with nested RecyclerView from a fragment but I would like to implement your way of onClick. Right now I have 2 RecyclerView adapter which… Read more »
Thanks a lot!!!
thanks lot bro
Nice tutorial. Can you implement json parsing with recyclerview card view combination? Thanks again.
Thanks Joseph. This tutorial does exactly that.
That’s cool. How can one do a similar thing with volley?
PLEASE HELP!!! when i try to open existing project code. Android studio throw a message Frameworks detected in android studio. How can i solve this ?
mRecyclerView.setLayoutManager() should work. In any case are you declaring RecyclerView inside ScrollView?
Unfortunately we don’t have any tutorial that explains spinner inside recycler view.
Checkout http://stacktips.com/tutorials/android/android-spinner-example for spinner example
Nilanchala You appreciate your prompt response, effective and place the spinner in the recyclerview and I can select it, my problem is: 1. The value that I select the spinner if this is not saved in the database. 2. When I go to join the activity to check if it… Read more »
You’re welcome. Happy that it helped you.
Hi, I have implemented a tab layout with fragments. But the code here is implemented by activity. I have to show the RecyclerView in one of the fragments. Can u help me with this public class CollegeListFragment extends Fragment { public CollegeListFragment() { // Required empty public constructor } @Override… Read more »
Hi Zhang, are you able to implement onclick on the listview items?? if yes, Please kindly show me how. or @PostAuthor can also show me how. Thanks
http://stackoverflow.com/questions/36498881/animate-gravity-layout-changes-of-floatingactionbutton-in-android?stw=2
I have a question … please reply me this question…
Hi JavaTechig am a fan of yours and i really enjoyed your tutorials, i neead your help can you please make the rss feed item show in a webview when clicked by a user i have tried so many times but it is not working see my code belo for… Read more »
Make sure layout height’s cardview is not “match_parent” !!
Remove padding in mainActivity
Hello Nilanchala; What a great video thanks for sharing, I have the following question: I have an application in which the first activity are all of which want to launch a new activity which is a recyclerview, and that the selecionar one of the buttons show me the pertienen information,… Read more »
Hi Nilanchala, thanks for sharing your knowledge: I have an application which has two buttons on the main activity, the idea is that by giving click on them, I send activity recyclerview which would be the same for the two buttons, the only thing is that by giving click button… Read more »
i am get getting a no adapter error in my fragment activity, so how can i do this in a activity
@dennismubamba:disqus I am getting a error in main activity when i am calling adapter in main activity. please see this:
http://stackoverflow.com/questions/37566355/adapter-not-working-while-implementing-recyclerview-and-cardview?noredirect=1#comment62620177_37566355
i developed android Recyclerview, every row have 1progressbar then i click on the item call download function from MainActivity thats work fine. i need to update specific progressbar.
m followng material design. so cn i replace fragment on the onClick() of cardview with passing some data from recyclerview adapter class to the another fragment?
how the way to call take it to the next class onClickListener. like the example, DetailActivity.java as the next class.
sorry, i’m a beginner…
how to way to call them to the next class onClicklistener. like the example, DetailActivity.java as the next class.
Sorry, i’m beginner :-)
Thanks for this tutorial ! I have an issue i think it’s my php file. It would be great if i can have the tutorial php code to compare with mine.
I think, something wrong with your list row layout.
I think you’re skipping the following code.
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
thanks for the reply, there was some problem with api but i got it now.
You should try this…it was working for me.
Thank you for this tutorial. It really helps a lot. Can you please explain a bit about the use of Card View in this? & Could you please tell me to do the same in eclipse?
abe bhai eclipse deprecate ho chuka hai,
studio pe kaam kar.
I am in process of updating all examples in this blog to Android studio project.
Perfect. All the best. (y)
Great tutorial! I didn’t need anything fancy just something short and sweet. This was perfect!
Hi,
Nilanchala
i use this code but in some items I can not get the images.
Can I know why?
This is a problem of size jpg or png format?
And also I can not have more than 10 items. What should I do?
I use the code but in some items I can not get the images.
Can I know why?
This is a problem of size jpg or png format?
My link is :
http://universfm.org/api/get_category_posts/?id=278
Thank you
Hello from Urkaine! Your tutorial is incrediable, perfect!!!!!!!!! THANK YOU !!!!!
Hi Nilanchala,
your tutorial is very good but on my projet, I can not get the images in some items .
Can I know why?
my link is :
http://universfm.org/api/get_category_posts/?id=278
just add this to xml of cardview
card_view:cardUseCompatPadding=”true”
i got this code from github, but it’s show configuration error, i cannot solve that error please help me…. anyone…
JavaTechig this tutorial is amazing would you perhaps give a link with the back-end code, thanks in advance :)
hii.. Nilanchala, I have added RecyclerView in my material tabs fragment, i am trying to add youtube channel videos using pagination to that recycler view from youtube data api v3 but i don’t know why my code dosen’t work … please can you tell me how can i solve this,… Read more »
hii Nilanchala, I have added recyclerView in material tabs , i am using volley to make request.. in my app i try to add list of videos from youtube channel using youtube data api v3, but something went wrong in implementing pagination in recyclerview… please can you tell me how… Read more »
hey man thanks for the tutorial. Am getting the error “RecyclerView﹕ No adapter attached; skipping layout” in my logcat and the application loads upto when it crushes . Wondering what am doing wrong , thanks.
I guess you’re missing to call following line
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
Hi, when I have no internet connection, the application stops
can you helps me?
Thanks for this post, helped me !!
hI @javatechig:disqus please provide a toturial that explain XML Parsing instead of JSON…i have some isuues with that.
Checkout this tutorial explains How to Use Picasso Image Loader Library in Android
For click event handling in RecyclerView, you won’t find any standard call back such as onListItemClick, you have to write your own click event handling in adapter class. Find a sample here that might help https://github.com/npanigrahy/Android-Lollipop-Navigation-Drawer/blob/master/app/src/main/java/com/javatechig/apps/nav/NavigationDrawerAdapter.java Secondly, for passing data such as array list it is recommended not to pass… Read more »
Checkout the sample code. Will soon post the tutorial on Javatechig.
https://github.com/npanigrahy/Android-Lollipop-Navigation-Drawer
Download Picasso image downloader library.
Shouldn’t you be using this bit of code instead in the dependancies section? :-)
From: http://square.github.io/picasso/
Code: compile ‘com.squareup.picasso:picasso:2.5.2’
Hi!
How works this sentences?
return (null != feedItemList ? feedItemList.size() : 0);
I don`t undertand exactly what.
Thanks! Great article.
Here i amusing ternary operation to make a null check. Otherwise it will throw a NullPointerException when feedItemList is null. The above code is same as
if(feedItemList !=null){
return feedItemList.size();
}else{
return 0;
}
Please read more about ternary operator here http://en.wikipedia.org/wiki/%3F:#Java
Thanks!
:-)
Thank you very much for posting this. I’ve been working literally all day trying to figure out how to refresh my RecycleView in a fragment with an AsyncTask. The second section above gave me what I needed, particularly resetting the adapter in onPostExecute.
We are glad it helped you.
Thanks!
But instead of
inflate(R.layout.list_row, null);
use
inflate(R.layout.list_row, viewGroup, false);
Thanks a lot!! Everything works perfect
You need to run it on a Android OS. So if you don’t want to use a android device you have to run it on a android emulator.. You can use the normal android emulator or you can take a look at Genymotion (in my opinion a better emulator than… Read more »
Thanks @Luizje