You are reading about Android Retrofit ListView Tutorial Example Parse JSON Step By Step.
Retrofit android tutorial will guide you to parse JSON data from the remote web server and then display this data in the ListView.
We will fetch/retrieve JSON data from MySQL database (server) using retrofit and will make custom listview with image and text.
In this tutorial, we will fetch the information like player name, city, country and image URL in JSON format with retrofit library.
Retrofit library makes our task easy to do http calls to the web service to retrieve the JSON data.
It also handles the cache of data in the proper manner.
Then a listview will showcase this information in a perfect format.
Last Look Of Retrofit ListView
Let us reach our goal step by step.
Step 1. Permission and Gradle lines
Open up your android studio and make a new fresh project with empty activity as a default activity.
When we want to get data from server, we need to use internet of the android device.
For this need, we will write one line in AndroidManifest.xml file. Below line will enable our app to use internet.
<uses-permission android:name="android.permission.INTERNET"/>
After this, let us add some lines in the build.gradle(Module:app) file as per the below
implementation 'com.squareup.retrofit2:retrofit:2.5.0' implementation 'com.squareup.retrofit2:converter-scalars:2.5.0' implementation 'com.squareup.picasso:picasso:2.71828'
- First line will add the required classes to use retrofit library in our project.
- Second line will enable us to use the coding lines of the scalar library.
- By default, retrofit will not give us the JSON response in a string format. Scalar helps us to convert the JSON data into the string format.
- Last line is for picasso library. This library will help us to load the images from URL and to maintain the image cache.
Step 2. Making Our Interface
Prepare a new JAVA class and give it a name MyInterface.java
Write down the below source code in MyInterface.java
import retrofit2.Call; import retrofit2.http.GET; public interface MyInterface { String JSONURL = "https://demonuts.com/Demonuts/JsonTest/Tennis/"; @GET("json_parsing.php") Call<String> getString(); }
- A string variable JSONURL contains the URL from which we will get our JSON data.
- @GET annotation holds the name of the php file.
- getString() function has the return type as a call back in the string format.
Step 3. Model class for ListView
Now make a new java class named ModelListView.java
Source code for ModelListView.java is looking like the following
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; }
- Types of information we are getting from JSON is like name, city, country etc.
- Above class includes getter ans setter information for all the types of the information.
- These methods will help us to maintain data between the listview and the adapter class.
Step 4. Special layout file
Create a new layout resource file named retro_lv.xml and write the below code snippet in this file.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:layout_width="100dp" android:layout_height="100dp" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:scaleType="fitXY" android:id="@+id/iv"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="100dp" android:layout_marginLeft="10dp" android:layout_marginTop="10dp" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_marginTop="5dp" android:layout_weight="1" android:id="@+id/name" android:text="ddd"/> <TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:id="@+id/country" android:text="ddd"/> <TextView android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="1" android:id="@+id/city" android:text="ddd"/> </LinearLayout> </LinearLayout>
- This file have one image view and three text views.
- We will fetch image from the URL in this image view.
- Textviews will hold the information like name, country, city etc.
Step 5. Retro Adapter
Time to make an adapter class for the listview.
Prepare a new class and named it as RetroAdapter.java
Following is the code structure for RetroAdapter.java class
import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; import java.util.ArrayList; public class RetroAdapter extends BaseAdapter { private Context context; private ArrayList<ModelListView> dataModelArrayList; public RetroAdapter(Context context, ArrayList<ModelListView> dataModelArrayList) { this.context = context; this.dataModelArrayList = dataModelArrayList; } @Override public int getViewTypeCount() { return getCount(); } @Override public int getItemViewType(int position) { return position; } @Override public int getCount() { return dataModelArrayList.size(); } @Override public Object getItem(int position) { return dataModelArrayList.get(position); } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { holder = new ViewHolder(); LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); convertView = inflater.inflate(R.layout.retro_lv, null, true); holder.iv = (ImageView) convertView.findViewById(R.id.iv); holder.tvname = (TextView) convertView.findViewById(R.id.name); holder.tvcountry = (TextView) convertView.findViewById(R.id.country); holder.tvcity = (TextView) convertView.findViewById(R.id.city); convertView.setTag(holder); }else { // the getTag returns the viewHolder object set as a tag to the view holder = (ViewHolder)convertView.getTag(); } Picasso.get().load(dataModelArrayList.get(position).getImgURL()).into(holder.iv); holder.tvname.setText("Name: "+dataModelArrayList.get(position).getName()); holder.tvcountry.setText("Country: "+dataModelArrayList.get(position).getCountry()); holder.tvcity.setText("City: "+dataModelArrayList.get(position).getCity()); return convertView; } private class ViewHolder { protected TextView tvname, tvcountry, tvcity; protected ImageView iv; } }
- Look at the constructor in the above adapter class. It has two parameters.
- First parameters will get context while other one will get the arraylist with the objects of the ModelListView class.
- getView() method contain the necessary coding lines to fill the information.
Following lines are populating the row of the listview.
Picasso.get().load(dataModelArrayList.get(position).getImgURL()).into(holder.iv); holder.tvname.setText("Name: "+dataModelArrayList.get(position).getName()); holder.tvcountry.setText("Country: "+dataModelArrayList.get(position).getCountry()); holder.tvcity.setText("City: "+dataModelArrayList.get(position).getCity());
- First line line will load the image from the URL using picasso library.
- Other three lines will fill the name, country and city respectively.
Step 6. Main Modifications
Now just need to change the main files.
First of all, add the below code snippet in the activity_main.xml file
<?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" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:textSize="26sp" android:text="Below ListView is populated from RETROFIT JSON Data" android:textColor="#000" /> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/lv" android:layout_marginTop="10dp"/> </LinearLayout>
- Above file holds one text view and one listview.
- Text view is static and it is saying that below listview have data which is parsed with retrofit.
Now in the MainActivity.java file, you should write the following coding lines
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.widget.ListView; 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 ListView listView; private RetroAdapter retroAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = findViewById(R.id.lv); getJSONResponse(); } private void getJSONResponse(){ Retrofit retrofit = new Retrofit.Builder() .baseUrl(MyInterface.JSONURL) .addConverterFactory(ScalarsConverterFactory.create()) .build(); MyInterface api = retrofit.create(MyInterface.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(); writeListView(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 writeListView(String response){ try { //getting the whole json object from the response JSONObject obj = new JSONObject(response); if(obj.optString("status").equals("true")){ ArrayList<ModelListView> modelListViewArrayList = new ArrayList<>(); JSONArray dataArray = obj.getJSONArray("data"); for (int i = 0; i < dataArray.length(); i++) { ModelListView modelListView = new ModelListView(); JSONObject dataobj = dataArray.getJSONObject(i); modelListView.setImgURL(dataobj.getString("imgURL")); modelListView.setName(dataobj.getString("name")); modelListView.setCountry(dataobj.getString("country")); modelListView.setCity(dataobj.getString("city")); modelListViewArrayList.add(modelListView); } retroAdapter = new RetroAdapter(this, modelListViewArrayList); listView.setAdapter(retroAdapter); }else { Toast.makeText(MainActivity.this, obj.optString("message")+"", Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { e.printStackTrace(); } } }
Deep Into Main Activity
Let us check what will main activity code actually do in this app.
First of all in onCreate() method, compiler will call getJSONResponse() method.
Source code for getJSONResponse() method is as the below
private void getJSONResponse(){ Retrofit retrofit = new Retrofit.Builder() .baseUrl(MyInterface.JSONURL) .addConverterFactory(ScalarsConverterFactory.create()) .build(); MyInterface api = retrofit.create(MyInterface.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(); writeListView(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) { } }); }
- Here, compiler will create the object of the Retrofit class. During this process, it will bind the URL using .baseUrl() method.
- Then compiler will create the object of the MyInterface class which we have created in Step 2.
- An object of the Call<String> will use call.enqueue() to make the http call.
- When system gives the final JSON response then compiler will call onResponse() method.
- Inside the onResponse() method, we will get the JSON response in the string format.
- Then call to writeListView() method will be taken place.
Code for writeListView() method is as the following
private void writeListView(String response){ try { //getting the whole json object from the response JSONObject obj = new JSONObject(response); if(obj.optString("status").equals("true")){ ArrayList<ModelListView> modelListViewArrayList = new ArrayList<>(); JSONArray dataArray = obj.getJSONArray("data"); for (int i = 0; i < dataArray.length(); i++) { ModelListView modelListView = new ModelListView(); JSONObject dataobj = dataArray.getJSONObject(i); modelListView.setImgURL(dataobj.getString("imgURL")); modelListView.setName(dataobj.getString("name")); modelListView.setCountry(dataobj.getString("country")); modelListView.setCity(dataobj.getString("city")); modelListViewArrayList.add(modelListView); } retroAdapter = new RetroAdapter(this, modelListViewArrayList); listView.setAdapter(retroAdapter); }else { Toast.makeText(MainActivity.this, obj.optString("message")+"", Toast.LENGTH_SHORT).show(); } } catch (JSONException e) { e.printStackTrace(); } }
Let us first check the JSON data which we get from the server.
{ "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 understand the writeListView() method and also check the JSON data simultaneously.
- Here, compiler will first get the json array from the field “data“
- Then it will run one for loop. In the every iteration of the for loop, compiler will fetch the information and will set it in the object of the ModelListView class.
- After the completion of the for loop, compiler will set the arraylist to the second parameter of the RetroAdapter.
Finally, adapter is set to the listview and whooom, our example is finish!!
Download Code for Android Retrofit ListView Example
Download Json_ListView_Retrofit Source Code