Create Multiple Columns ListView from JSON Data using Retrofit2 in Android Example

In this example, we will create a sample application with single activity having a ListView with custom BaseAdapter to have multi columns with data from JSON object which we will get from dummy JSON file on the server. To make real server requests we will use Retrofit2.

This example app will discuss a challenge to parse JSON Object into ListView.

Let’s quickly start with an empty sample project.

Our directory structure will look like this.

Step 1) Add Retrofit2, okkhttp3, Gson, Converter Gson dependencies into Module: app build.gradle.

Copy paste these in “dependencies” section after that click on “Sync now“.

compile 'com.google.code.gson:gson:2.8.2'
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'

Step 2) Create a model file "MyModel" to map response from server side.

model/MyModel.java

package com.freakyjolly.listviewjsonexample.model;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;

public class MyModel {

    @SerializedName("results")
    @Expose
    private ArrayList results;
    @SerializedName("phone")
    @Expose
    private String phone;
    @SerializedName("name")
    @Expose
    private String name;

    public ArrayList getResults() {
        return results;
    }

    public void setResults(ArrayList results) {
        this.results = results;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

 

Step 3) Create three file under "service" package

- ApiClientBuilder class file ( Will have Retrofit2 and okhttp3 initialization variables ).
- ApiService ( A service file having calls to server )
- ApiClient ( interface file defining nature and type of call )

ApiClientBuilder.java

package com.freakyjolly.listviewjsonexample.service;

import com.google.gson.GsonBuilder;

import java.io.IOException;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class ApiClientBuilder {
    public static final String BASE_URL = "https://freakyjolly.com";
    private static Retrofit retrofit = null;
    public static OkHttpClient.Builder httpClient;
    public static Retrofit getClient() {
        //http logging interceptor will give us the information about web service call reqponse.
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);

        httpClient = new OkHttpClient.Builder();

        httpClient.addInterceptor(logging);

        //We should add headers for the request.
        httpClient.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request original = chain.request();

                Request request = original.newBuilder()
                        .header("Content-Type", "multipart/form-data")
                        .method(original.method(), original.body())
                        .build();

                return chain.proceed(request);
            }
        });

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()))
                .client(httpClient.build())
                .build();

        return retrofit;
    }

    public static ApiClient getMGClient() {

        return getClient().create(ApiClient.class);
    }

}

ApiService.java

package com.freakyjolly.listviewjsonexample.service;

import com.freakyjolly.listviewjsonexample.model.MyModel;

import retrofit2.Call;
import retrofit2.Callback;

public class ApiService {

    public void getClientList(Callback<MyModel> callback) {

        ApiClient service = ApiClientBuilder.getMGClient();

        Call<MyModel> result =  service.getJSONData();

        result.enqueue(callback);

    }


}

ApiClient.java

package com.freakyjolly.listviewjsonexample.service;

import com.freakyjolly.listviewjsonexample.model.MyModel;

import org.json.JSONArray;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.POST;

public interface ApiClient {
    @GET("/demo/dummyjson/name_phone.json")
    Call<MyModel> getJSONData();
}

 

Step 4) MainActivity class will have a server call, in response, it will call custom BaseAdapter.

MainActivity.java

package com.freakyjolly.listviewjsonexample;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;

import com.freakyjolly.listviewjsonexample.model.MyModel;
import com.freakyjolly.listviewjsonexample.service.ApiService;

import java.util.ArrayList;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends AppCompatActivity {


    ListView listView ;
    String TAG = "MainActivity";
    ArrayList<MyModel> dummyData =new ArrayList<>();
    static CustomListAdapter customListAdapter;
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Make a server call and get data
        getdata();
    }


    public void getdata() {
        try {

            new ApiService().getClientList( new Callback<MyModel>() {
                @Override
                public void onResponse(Call<MyModel> call, Response<MyModel> response) {

                    Log.d(TAG, "onResponse: response..."+response);

                    /*

                    {
                      "results": [
                        {
                          "phone": "+91783XXXX345",
                          "name": "FreakyJolly"
                        },
                        {
                          "phone": "+9178XXXX66",
                          "name": "Olivia"
                        },
                        {
                          "phone": "+9178XXXX66",
                          "name": "Isla"
                        },
                        {
                          "phone": "+9178XXXX66",
                          "name": "Emily"
                        },
                        {
                          "phone": "+9178XXXX66",
                          "name": "Amelia"
                        },
                        {
                          "phone": "+9178XXXX66",
                          "name": "Sophia"
                        }],
                      "statusCode": "1",
                      "count": "2"
                    }

                    */

                    //This will get result part from dummy JSON response
                    dummyData = response.body().getResults();
                    createListView();
                }
                @Override
                public void onFailure(Call<MyModel> call, Throwable t) {

                    Log.d(TAG, "onFailure: response...");
                }
            });

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    public  void createListView(){
        //Send JSON object list to custom BaseAdapter
        customListAdapter = new CustomListAdapter(getApplicationContext(), dummyData);
        listView = (ListView) findViewById(R.id.listShowJSONData);
        listView.setAdapter(customListAdapter);
    }


}

Step 5) Create List layout Adapter class "CustomListAdapter" extending "BaseAdapter"

CustomListAdapter

package com.freakyjolly.listviewjsonexample;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.freakyjolly.listviewjsonexample.model.MyModel;
import com.google.gson.internal.LinkedTreeMap;

import java.util.ArrayList;

public class CustomListAdapter extends BaseAdapter {


    Context c;
    ArrayList<MyModel> users;

    public CustomListAdapter(Context c, ArrayList<MyModel> users) {
        this.c = c;
        this.users = users;
    }

    @Override
    public int getCount() {
        return users.size();
    }

    @Override
    public MyModel getItem(int i) {
        return this.users.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    @Override
    public View getView(final int i, View view, ViewGroup viewGroup) {
        if(view==null)
        {
            view= LayoutInflater.from(c).inflate(R.layout.json_data_list,viewGroup,false);
        }

        TextView mUserDetails = (TextView) view.findViewById(R.id.userDetails);
        TextView mUserStatus = (TextView) view.findViewById(R.id.userStatus);


        Object getrow = this.users.get(i);
        LinkedTreeMap<Object,Object> rowmap = (LinkedTreeMap) getrow;
        String name = rowmap.get("name").toString();
        String phone = rowmap.get("phone").toString();

        mUserDetails.setText(name);
        mUserStatus.setText(phone);

        return view;
    }

}

 

Step 6) Now we work on Layouts MainActivity (activity_main.xml) and Custom List layout (json_data_list.xml)

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/listShowJSONData"
        android:layout_width="368dp"
        android:layout_height="398dp"
        android:layout_margin="10dp"
        android:layout_marginTop="8dp"
        android:padding="10dp"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        tools:layout_editor_absoluteX="8dp" />


</android.support.constraint.ConstraintLayout>

json_data_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/userDetails"
        android:layout_width="95dp"
        android:layout_height="match_parent"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="10dp"
        android:layout_weight="1"
        android:text="TextView"
        android:textColor="#000000"
        android:textIsSelectable="true" />

    <TextView
        android:id="@+id/userStatus"
        android:layout_width="83dp"
        android:layout_height="match_parent"
        android:layout_marginBottom="10dp"
        android:layout_marginTop="10dp"
        android:layout_weight="1"
        android:text="TextView"
        android:textColor="#000000" />


</LinearLayout>

 

Step 7) Last But Not Least 🙂 we need to add "Internet" permission as we are making the real server call.

Open "AndroidManifest.xml" then add below line immediately after "manifest" before "application" tag.

<uses-permission android:name="android.permission.INTERNET" />

Find source find on Github here

That's it Guys let me know if you face any issue in implementing this.

Thanks and happy Coding 🙂

Leave a Comment

Your email address will not be published. Required fields are marked *