Welcome to Kotlin Volley ListView JSON Parser Android Example.
We will parse the JSON from URL using volley and then we will show the data in the listview.
Data from the MySQL database server will be in JSON string format.
We will use Listview with image and text to show the data in proper manner.
Volley library will help us to fetch the data from the URL.
First of all, check the following coding lines to see the output.
Fetching the Volley
Make a new project inside the android studio.
Now go to the build.gradle(Module:app) file and add the following lines
implementation 'com.android.volley:volley:1.1.1' implementation 'com.squareup.picasso:picasso:2.71828'
First line is for the volley. It will allow us to use the volley library in our project.
Second line will integrate the Picasso library in our project.
Picasso will fetch the image from it’s URL withing the fraction of second.
Enabling Internet
To fetch the JSON data from the URL, we need to use the internet.
For this, we need one permission in the AndroidManifest.xml file.
So open up your AndroidManifest.xml file and write the below line in it
<uses-permission android:name="android.permission.INTERNET"/>
This permission is usual and not much harmful to user security.
So we do not need to ask for the runtime permission.
Layout File For ListView
Navigate to the app->res->layout directory.
Inside this directory, make a new XML file and give it a name like lv_player.xml
Give the below source code structure to the lv_player.xml 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>
Above file is making the layout for the each child row of the listview.
File is containing one image view and three text views.
Data Structure
Now let create a class which will maintain the data structure for the Listview.
Create a new Kotlin file with the name as DataModel.kt
Inside this DataModel.kt file, add some new source lines like the following
class DataModel { var name: String? = null var country: String? = null var city: String? = null var imgURL: String? = null fun getNames(): String { return name.toString() } fun setNames(name: String) { this.name = name } fun getCountrys(): String { return country.toString() } fun setCountrys(country: String) { this.country = country } fun getCitys(): String { return city.toString() } fun setCitys(city: String) { this.city = city } fun getimgURLs(): String { return imgURL.toString() } fun setimgURLs(imgURL: String) { this.imgURL = imgURL } }
Above model file has four string variables : name, country, city and imgURL
For all of these four variables, I have written getter and setter methods.
These methods will save and fetch the data from arraylists.
We will use these methods in the adapter and main activity file.
Adapter of the ListView
Now create a new Kotlin class and give it a name like ListAdapter.kt
You should write the following coding lines into the ListAdapter.kt file.
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 class ListAdapter(private val context: Context, private val dataModelArrayList: ArrayList<DataModel>) : BaseAdapter() { override fun getViewTypeCount(): Int { return count } override fun getItemViewType(position: Int): Int { return position } override fun getCount(): Int { return dataModelArrayList.size } override fun getItem(position: Int): Any { return dataModelArrayList[position] } override fun getItemId(position: Int): Long { return 0 } override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { var convertView = convertView val holder: ViewHolder if (convertView == null) { holder = ViewHolder() val inflater = context .getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater convertView = inflater.inflate(R.layout.lv_player, null, true) holder.iv = convertView!!.findViewById<View>(R.id.iv) as ImageView holder.tvname = convertView.findViewById<View>(R.id.name) as TextView holder.tvcountry = convertView.findViewById<View>(R.id.country) as TextView holder.tvcity = convertView.findViewById<View>(R.id.city) as TextView convertView.tag = holder } else { // the getTag returns the viewHolder object set as a tag to the view holder = convertView.tag as ViewHolder } Picasso.get().load(dataModelArrayList[position].getimgURLs()).into(holder.iv) holder.tvname!!.text = "Name: " + dataModelArrayList[position].getNames() holder.tvcountry!!.text = "Country: " + dataModelArrayList[position].getCountrys() holder.tvcity!!.text = "City: " + dataModelArrayList[position].getCitys() return convertView } private inner class ViewHolder { var tvname: TextView? = null var tvcountry: TextView? = null var tvcity: TextView? = null var iv: ImageView? = null } }
This adapter class place the data into each child row of the listview.
See the following line from the getView() method which is in the above code
convertView = inflater.inflate(R.layout.lv_player, null, true)
This line is inflating the lv_player.xml file. So child row of listview will have the layout like lv_player.xml
Now focus on the following coding lines
Picasso.get().load(dataModelArrayList[position].getimgURLs()).into(holder.iv) holder.tvname!!.text = "Name: " + dataModelArrayList[position].getNames() holder.tvcountry!!.text = "Country: " + dataModelArrayList[position].getCountrys() holder.tvcity!!.text = "City: " + dataModelArrayList[position].getCitys()
First line using the Picasso class. It will help us to fetch the image from the URL.
Second , third and fourth lines will set the text value inside three text views.
Main Files
Inside your activity_main.xml file, add the below line
<?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:text="Below ListView is populated from JSON Data" android:textColor="#000"/> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/lv" android:layout_marginTop="10dp"> </ListView> </LinearLayout>
Above main layout file have one text view and one listview.
Now write down the code of the below lines inside the MainActivity.kt
import android.app.ProgressDialog import android.content.Context import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.widget.ListView import android.widget.Toast import com.android.volley.Request import com.android.volley.RequestQueue import com.android.volley.Response import com.android.volley.VolleyError import com.android.volley.toolbox.StringRequest import com.android.volley.toolbox.Volley import org.json.JSONArray import org.json.JSONException import org.json.JSONObject import java.util.ArrayList class MainActivity : AppCompatActivity() { private val URLstring = "https://demonuts.com/Demonuts/JsonTest/Tennis/json_parsing.php" private var listView: ListView? = null internal lateinit var dataModelArrayList: ArrayList<DataModel> private var listAdapter: ListAdapter? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) listView = findViewById(R.id.lv) retrieveJSON() } private fun retrieveJSON() { showSimpleProgressDialog(this, "Loading...", "Fetching Json", false) val stringRequest = StringRequest(Request.Method.GET, URLstring, Response.Listener { response -> Log.d("strrrrr", ">>$response") try { val obj = JSONObject(response) if (obj.optString("status") == "true") { dataModelArrayList = ArrayList() val dataArray = obj.getJSONArray("data") for (i in 0 until dataArray.length()) { val playerModel = DataModel() val dataobj = dataArray.getJSONObject(i) playerModel.setNames(dataobj.getString("name")) playerModel.setCountrys(dataobj.getString("country")) playerModel.setCitys(dataobj.getString("city")) playerModel.setimgURLs(dataobj.getString("imgURL")) dataModelArrayList.add(playerModel) } setupListview() } } catch (e: JSONException) { e.printStackTrace() } }, Response.ErrorListener { error -> //displaying the error in toast if occurrs Toast.makeText(applicationContext, error.message, Toast.LENGTH_SHORT).show() }) // request queue val requestQueue = Volley.newRequestQueue(this) requestQueue.add(stringRequest) } private fun setupListview() { removeSimpleProgressDialog() //will remove progress dialog listAdapter = ListAdapter(this, dataModelArrayList) listView!!.adapter = listAdapter } companion object { private var mProgressDialog: ProgressDialog? = null fun removeSimpleProgressDialog() { try { if (mProgressDialog != null) { if (mProgressDialog!!.isShowing) { mProgressDialog!!.dismiss() mProgressDialog = null } } } catch (ie: IllegalArgumentException) { ie.printStackTrace() } catch (re: RuntimeException) { re.printStackTrace() } catch (e: Exception) { e.printStackTrace() } } fun showSimpleProgressDialog( context: Context, title: String, msg: String, isCancelable: Boolean ) { try { if (mProgressDialog == null) { mProgressDialog = ProgressDialog.show(context, title, msg) mProgressDialog!!.setCancelable(isCancelable) } if (!mProgressDialog!!.isShowing) { mProgressDialog!!.show() } } catch (ie: IllegalArgumentException) { ie.printStackTrace() } catch (re: RuntimeException) { re.printStackTrace() } catch (e: Exception) { e.printStackTrace() } } } }
Now focus on the below coding lines
private val URLstring = "https://demonuts.com/Demonuts/JsonTest/Tennis/json_parsing.php" private var listView: ListView? = null internal lateinit var dataModelArrayList: ArrayList<DataModel> private var listAdapter: ListAdapter? = null
First line defining a variable which holds the URL to the JSON data in the string format.
Second line is defining an object of the ListView class.
Third is the arraylist with the objects of the DataModel class.
Fourth one is the object of the ListAdapter class.
Look at the retrieveJSON() method inside the onCreate() method.
Compiler will first show the loading dialog using the showSimpleProgressDialog() method.
Then after it will make a GET request to the URL to get the JSON data.
After getting the JSON data, compiler will go through one for loop. This loop will create a data source dataModelArrayList
Below is the JSON data which we are getting from the MySQL database.
{ "status": "true", "message": "Data fetched successfully!", "data": [ { "id": "1", "name": "Roger Federer", "country": "Switzerland", "city": "Basel", "imgURL": "https://demonuts.com/Demonuts/SampleImages/roger.jpg" }, { "id": "2", "name": "Rafael Nadal", "country": "Spain", "city": "Madrid", "imgURL": "https://demonuts.com/Demonuts/SampleImages/nadal.jpg" }, { "id": "3", "name": "Novak Djokovic", "country": "Serbia", "city": "Monaco", "imgURL": "https://demonuts.com/Demonuts/SampleImages/djoko.jpg" }, { "id": "4", "name": "Andy Murray", "country": "United Kingdom", "city": "London", "imgURL": "https://demonuts.com/Demonuts/SampleImages/murray.jpg" }, { "id": "5", "name": "Maria Sharapova", "country": "Russia", "city": "Moscow", "imgURL": "https://demonuts.com/Demonuts/SampleImages/shara.jpg" }, { "id": "6", "name": "Caroline Wozniacki", "country": "Denmark", "city": "Odense", "imgURL": "https://demonuts.com/Demonuts/SampleImages/woz.jpg" }, { "id": "7", "name": "Eugenie Bouchard", "country": "Canada", "city": " Montreal", "imgURL": "https://demonuts.com/Demonuts/SampleImages/bou.png" }, { "id": "8", "name": "Ana Ivanovic", "country": "Serbia", "city": "Belgrade", "imgURL": "https://demonuts.com/Demonuts/SampleImages/iva.jpg" } ] }
setupListview() method will create the adapter using the data source dataModelArrayList
Then after it will attach the adapter to the listview.