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 Reply