This post is about Android RecyclerView Retrofit Tutorial With Example.
Android JSON parsing and display with recyclerview using retrofit is today’s topic.
In this tutorial, we will retrieve JSON data from MySQL database and then we will set this data in Recycler View.
Retrofit library is useful to make http calls seamlessly and it also saves time.
If we make http call with android’s in built classes then this task can be a little tricky.
Following is Output
Step 1. Gradle and Permission Tasks
Create a new project in the android studio. Select Empty activity during the process of making a new project.
Now in the AndroidManifest.xml file, add the following line
<uses-permission android:name="android.permission.INTERNET" />
- Above line will enable our app to use the internet so that we can fetch JSON data from web server or MySQL database.
- Now we need to use five different libraries in this project.
Write down the following coding lines in build.gradle(Module: app) file
implementation 'com.squareup.retrofit2:retrofit:2.5.0' implementation 'com.squareup.retrofit2:converter-scalars:2.5.0' implementation 'com.squareup.picasso:picasso:2.71828' implementation 'com.android.support:recyclerview-v7:27.1.1' implementation 'com.android.support:cardview-v7:27.1.1'
- First coding line will fetch the required classes to use the retrofit library.
- Second line will enable us to use the scalars library. This library will help us to convert the JSON response into the string format.
- Third one will allow us to use Picasso library which will load the images from the URL for us.
- Fourth line is for recycler view.
- And last one is for card view because recycler view and card view are not added to the default UI widgets (like text view, edittext, list view etc.) in the android system.
Step 2. Required Interface
Create a new JAVA class. Give it a name like RecyclerInterface.java and add the following source code in it
import retrofit2.Call; import retrofit2.http.GET; public interface RecyclerInterface { String JSONURL = "https://demonuts.com/Demonuts/JsonTest/Tennis/"; @GET("json_parsing.php") Call<String> getString(); }
- A string variable JSONURL holds the URL of the json file in the string format.
- Name of the PHP file is not included in the string variable but it is present in the @GET annotation.
- Then a method is defined as the getString() which has the return type as Call<String>.
Step 3. Model For Retrofit
Make a new JAVA class and call it as ModelRecycler.java
Source code for ModelRecycler.java class is as the following
public class ModelRecycler { private String name, country, city, imgURL; public String getImgURL(){ return imgURL; } public void setImgURL(String imgURL){ this.imgURL = imgURL; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } }
- Our JSON data has certain types of information such as player’s name, country, city and URL of the image.
- Model class have getter and setter methods for all these information types.
- Such type of model class helps us to maintain proper data structure while interacting with the RecyclerView.
Step 4. Layout File for RecyclerView
Create a new layout file under res->layout directory.
Name of this file should be retro_item.xml
Source code for this file is as per the below
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" app:cardCornerRadius="5dp"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/iv" android:layout_width="100dp" android:layout_height="100dp" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:scaleType="fitXY" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="100dp" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:orientation="vertical"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_marginTop="5dp" android:layout_weight="1" android:text="ddd" android:textColor="#000" android:textStyle="bold" /> <TextView android:id="@+id/country" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:text="ddd" android:textColor="#000" android:textStyle="bold" /> <TextView android:id="@+id/city" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:text="ddd" android:textColor="#000" android:textStyle="bold" /> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView> </LinearLayout>
- I have written one image view and three text views in this file.
- Picasso will fetch will image in this image view while text views will hold the information like country, name and city.
- All the rows of the recyclerview will get their look and feel from this layout file.
Step 5. Adapter For Retrofit RecyclerView
Time to write the adapter file to populate our recycler view.
Create a new JAVA class and set it’s name as RetrofitAdapter.java
Following is the code structure for RetrofitAdapter.java class
import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; import java.util.ArrayList; public class RetrofitAdapter extends RecyclerView.Adapter<RetrofitAdapter.MyViewHolder> { private LayoutInflater inflater; private ArrayList<ModelRecycler> dataModelArrayList; public RetrofitAdapter(Context ctx, ArrayList<ModelRecycler> dataModelArrayList){ inflater = LayoutInflater.from(ctx); this.dataModelArrayList = dataModelArrayList; } @Override public RetrofitAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = inflater.inflate(R.layout.retro_item, parent, false); MyViewHolder holder = new MyViewHolder(view); return holder; } @Override public void onBindViewHolder(RetrofitAdapter.MyViewHolder holder, int position) { Picasso.get().load(dataModelArrayList.get(position).getImgURL()).into(holder.iv); holder.name.setText(dataModelArrayList.get(position).getName()); holder.country.setText(dataModelArrayList.get(position).getCountry()); holder.city.setText(dataModelArrayList.get(position).getCity()); } @Override public int getItemCount() { return dataModelArrayList.size(); } class MyViewHolder extends RecyclerView.ViewHolder{ TextView country, name, city; ImageView iv; public MyViewHolder(View itemView) { super(itemView); country = (TextView) itemView.findViewById(R.id.country); name = (TextView) itemView.findViewById(R.id.name); city = (TextView) itemView.findViewById(R.id.city); iv = (ImageView) itemView.findViewById(R.id.iv); } } }
- First of all, look at the second parameter of the constructor. It has arraylist with the objects of the ModelRecycler class.
- This arraylist will work as the data source in this adapter.
- Now read the onBindViewHolder() method. Compiler will fill the information using this method.
- First line inside onBindViewHolder() method will load the image from URL using Picasso library.
- Second, third and fourth lines will set the information like name, country and city respectively in the text views.
Step 6. Main Activity files
At last but not least, we need to change the writings for main files.
In your activity_main.xml file, add the below code lines
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="#15e6e6" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="Below RecyclerView is populated from Retrofit JSON Data" android:textColor="#fff" android:textStyle="bold"/> <android.support.v7.widget.RecyclerView android:id="@+id/recycler" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp" android:layout_marginTop="15dp"/> </LinearLayout>
- One text view and a recycler view is present in the main layout file.
- Text view has constant value and it is saying like “Recyclerview has JSON data which is fetched with retrofit.”
Now in the MainActivity.java file, you should add the following code snippet
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.widget.Toast; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import retrofit2.Retrofit; import retrofit2.converter.scalars.ScalarsConverterFactory; public class MainActivity extends AppCompatActivity { private RetrofitAdapter retrofitAdapter; private RecyclerView recyclerView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView = findViewById(R.id.recycler); fetchJSON(); } private void fetchJSON(){ Retrofit retrofit = new Retrofit.Builder() .baseUrl(RecyclerInterface.JSONURL) .addConverterFactory(ScalarsConverterFactory.create()) .build(); RecyclerInterface api = retrofit.create(RecyclerInterface.class); Call<String> call = api.getString(); call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { Log.i("Responsestring", response.body().toString()); //Toast.makeText() if (response.isSuccessful()) { if (response.body() != null) { Log.i("onSuccess", response.body().toString()); String jsonresponse = response.body().toString(); writeRecycler(jsonresponse); } else { Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show(); } } } @Override public void onFailure(Call<String> call, Throwable t) { } }); } private void writeRecycler(String response){ try { //getting the whole json object from the response JSONObject obj = new JSONObject(response); if(obj.optString("status").equals("true")){ ArrayList<ModelRecycler> modelRecyclerArrayList = new ArrayList<>(); JSONArray dataArray = obj.getJSONArray("data"); for (int i = 0; i < dataArray.length(); i++) { ModelRecycler modelRecycler = new ModelRecycler(); JSONObject dataobj = dataArray.getJSONObject(i); modelRecycler.setImgURL(dataobj.getString("imgURL")); modelRecycler.setName(dataobj.getString("name")); modelRecycler.setCountry(dataobj.getString("country")); modelRecycler.setCity(dataobj.getString("city")); modelRecyclerArrayList.add(modelRecycler); } retrofitAdapter = new RetrofitAdapter(this,modelRecyclerArrayList); recyclerView.setAdapter(retrofitAdapter); recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false)); }else { Toast.makeText(MainActivity.this, obj.optString("message")+"", Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { e.printStackTrace(); } } }
Main Activity Roots
Inside onCreate() method, compiler will call fetchJSON() method.
Coding lines for fetchJSON() method is as the following
private void fetchJSON(){ Retrofit retrofit = new Retrofit.Builder() .baseUrl(RecyclerInterface.JSONURL) .addConverterFactory(ScalarsConverterFactory.create()) .build(); RecyclerInterface api = retrofit.create(RecyclerInterface.class); Call<String> call = api.getString(); call.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { Log.i("Responsestring", response.body().toString()); //Toast.makeText() if (response.isSuccessful()) { if (response.body() != null) { Log.i("onSuccess", response.body().toString()); String jsonresponse = response.body().toString(); writeRecycler(jsonresponse); } else { Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show(); } } } @Override public void onFailure(Call<String> call, Throwable t) { } }); }
- First task is to create the object of the Retrofit class. Here, .baseUrl() contains the URL to which we will make the http call.
- Then compiler will create the object of the RecyclerInterface class which we have made during the step 2.
- After that, compiler will make the call object and using it, it will execute the .enqueue() method.
- Until now, retrofit have make the http call to the URL. When server gives the response, compiler will call onResponse() method.
- Here we will get our JSON response in string format. Then compiler will call writeRecycler() method.
Before we read writeRecycler() method, let us first check the JSON STRUCTURE
{ "status": "true", "message": "Data fetched successfully!", "data": [ { "id": "1", "name": "Roger Federer", "country": "Switzerland", "city": "Basel" }, { "id": "2", "name": "Rafael Nadal", "country": "Spain", "city": "Madrid" }, { "id": "3", "name": "Novak Djokovic", "country": "Serbia", "city": "Monaco" }, { "id": "4", "name": "Andy Murray", "country": "United Kingdom", "city": "London" }, { "id": "5", "name": "Maria Sharapova", "country": "Russia", "city": "Moscow" }, { "id": "6", "name": "Caroline Wozniacki", "country": "Denmark", "city": "Odense" }, { "id": "7", "name": "Eugenie Bouchard", "country": "Canada", "city": " Montreal" }, { "id": "8", "name": "Ana Ivanovic", "country": "Serbia", "city": "Belgrade" } ] }
Now following is the code for writeRecycler() method
private void writeRecycler(String response){ try { //getting the whole json object from the response JSONObject obj = new JSONObject(response); if(obj.optString("status").equals("true")){ ArrayList<ModelRecycler> modelRecyclerArrayList = new ArrayList<>(); JSONArray dataArray = obj.getJSONArray("data"); for (int i = 0; i < dataArray.length(); i++) { ModelRecycler modelRecycler = new ModelRecycler(); JSONObject dataobj = dataArray.getJSONObject(i); modelRecycler.setImgURL(dataobj.getString("imgURL")); modelRecycler.setName(dataobj.getString("name")); modelRecycler.setCountry(dataobj.getString("country")); modelRecycler.setCity(dataobj.getString("city")); modelRecyclerArrayList.add(modelRecycler); } retrofitAdapter = new RetrofitAdapter(this,modelRecyclerArrayList); recyclerView.setAdapter(retrofitAdapter); recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false)); }else { Toast.makeText(MainActivity.this, obj.optString("message")+"", Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { e.printStackTrace(); } }
- First of all, compiler will check the status field from JSON. If it has value as true then it will parse one JSONArray.
- Field named “data” holds the json array and compiler will parse it in object of the ArrayList<ModelRecycler>.
- Then compiler will run one for loop.
- During the every iteration of for loop, system set the information using various setter methods of the ModelRecycler class.
- After the completion of the for loop, compiler create the object of the RetrofitAdapter class and will bind it with the recycler view.