Kotlin Parse JSON From Url Android Example is the main focus.
You will learn how to make HTTP Request to get data in JSON format from remote server in Kotlin android.
We will use one external github library called Fuel to simplify this http request process.
First of all, see the following video for output.
Step 1. Giving Permission
We need to have internet for making http requests. For this, add the below line in AndroidManifest.xml file.
<uses-permission android:name="android.permission.INTERNET" />
Above line will simply allow our app to use the internet of the android device.
This permission is light weight in terms of user privacy so we do not need to implement runtime permissions.
Step 2. Adding Library With Gradle
To use the github library in our project, we need to integrate it via Gradle.
So open your build.gradle(Module:app) file and add the following line
implementation 'com.github.kittinunf.fuel:fuel-android:1.15.1'
It will simply enable us to use directly classes of fuel library. Here, I am using version number 1.15.1 of fuel library. You need to change this version number according to version of your Kotlin.
You can find more information about fuel library here.
Step 3. Making custom Layout File and Model
Now let us create one layout file that will help us to create the look and feel of a listview rows.
Make a new file under app->res->layout directory and give it a name like lv_item.xml
You need to add the following source code lines in this lv_item.xml
<?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" android:padding="10dp" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#000" android:orientation="vertical"> <TextView android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#fff" android:layout_marginTop="10dp" android:gravity="center_vertical" android:textAppearance="?android:attr/textAppearanceMedium" android:paddingLeft="10dp" android:text="Name" /> <TextView android:id="@+id/country" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#fff" android:gravity="center_vertical" android:textAppearance="?android:attr/textAppearanceMedium" android:paddingLeft="10dp" android:text="Country" /> <TextView android:id="@+id/city" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#fff" android:gravity="center_vertical" android:textAppearance="?android:attr/textAppearanceMedium" android:paddingLeft="10dp" android:text="City" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="10dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="@color/colorAccent"/> </LinearLayout>
Above file mainly includes three text views. One is for name, another is for country and last one is for city.
I have also added one view to use it as a divider between two child rows of list view.
After this, let us make one kotlin file to set it as a model class.
Create a new Kotlin file and give it a name like PlayersModel.kt and write the below source code in it.
class PlayersModel { var name: String? = null var country: String? = null var city: String? = null fun getNames(): String { return name.toString() } fun setNames(name: String) { this.name = name } fun getCountrys(): String { return country.toString() } fun setCountrys(name: String) { this.country = name } fun getCitys(): String { return city.toString() } fun setCitys(name: String) { this.city = name } }
This file have three variables as name, country and city.
It also includes getter and setter methods for all these three variables.
This methods will help us in adapter class for data maintenance.
Step 4. Writing Adapter
We need one adapter class, which will provide the data to the listview.
So, make a new Kotlin class and set it’s name as CustomAdapter.kt
Add the below source code lines in CustomAdapter.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.TextView import java.util.ArrayList /** * Created by Parsania Hardik on 03-Jan-17. */ class CustomeAdapter(private val context: Context, private val playersModelArrayList: ArrayList<PlayersModel>) : BaseAdapter() { override fun getViewTypeCount(): Int { return count } override fun getItemViewType(position: Int): Int { return position } override fun getCount(): Int { return playersModelArrayList.size } override fun getItem(position: Int): Any { return playersModelArrayList[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_item, null, true) holder.tvname = convertView!!.findViewById(R.id.name) as TextView holder.tvcountry = convertView.findViewById(R.id.country) as TextView holder.tvcity = convertView.findViewById(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 } holder.tvname!!.text = "Name: " + playersModelArrayList[position].getNames() holder.tvcountry!!.text = "Country: " + playersModelArrayList[position].getCountrys() holder.tvcity!!.text = "City: " + playersModelArrayList[position].getCitys() return convertView } private inner class ViewHolder { var tvname: TextView? = null var tvcountry: TextView? = null var tvcity: TextView? = null } }
Look at the class declaration line. This adapter will get context and playersModelArrayList in the parameter.
Now, focus on the below code
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_item, null, true) holder.tvname = convertView!!.findViewById(R.id.name) as TextView holder.tvcountry = convertView.findViewById(R.id.country) as TextView holder.tvcity = convertView.findViewById(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 } holder.tvname!!.text = "Name: " + playersModelArrayList[position].getNames() holder.tvcountry!!.text = "Country: " + playersModelArrayList[position].getCountrys() holder.tvcity!!.text = "City: " + playersModelArrayList[position].getCitys() return convertView }
Above is the code for getView() method. This method will first inflate the lv_item.xml file.
Then it will find the text views using ids.
After this, it will set the values on all the three text views using playersModelArrayList
Step 5. Main Works
In our last step, we will update main files like activity_main.xml and MainActivity.kt
So first of all, update the code lines of activity_main.xml file as per the following
<?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="match_parent" android:background="@color/colorAccent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_marginTop="10dp" android:textSize="20sp" android:textColor="#000" android:text="Data from JSON Parsing"/> <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/lv"/> </LinearLayout>
Two main tags are there : Text View and List View
A text view is static and it will not change it’s value in kotlin class.
List view is what we will use to bind the json data which we will fetch from the URL.
In MainActivity.kt class, add the below code snippet
import android.support.v7.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.widget.ListView import org.json.JSONException import org.json.JSONObject import com.github.kittinunf.fuel.Fuel import com.github.kittinunf.fuel.android.extension.responseJson import java.util.ArrayList class MainActivity : AppCompatActivity() { internal var URL = "https://demonuts.com/Demonuts/JsonTest/Tennis/json_parsing.php" private val jsoncode = 1 private var listView: ListView? = null private var playersModelArrayList: ArrayList<PlayersModel>? = null private var customeAdapter: CustomeAdapter? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) listView = findViewById(R.id.lv) as ListView sampleKo() } private fun sampleKo() { //https://github.com/androidmads/KotlinFuelHttpSample/blob/master/app/src/main/java/com/androidmads/kotlinfuelhttpsample/MainActivity.kt //https://github.com/kittinunf/Fuel/blob/1.16.0/README.md try { Fuel.post(URL, listOf()).responseJson { request, response, result -> Log.d("plzzzzz", result.get().content) onTaskCompleted(result.get().content) } } catch (e: Exception) { } finally { } } fun onTaskCompleted(response: String) { Log.d("responsejson", response) playersModelArrayList = getInfo(response) customeAdapter = CustomeAdapter(this, playersModelArrayList!!) listView!!.adapter = customeAdapter } fun getInfo(response: String): ArrayList<PlayersModel> { val playersModelArrayList = ArrayList<PlayersModel>() try { val jsonObject = JSONObject(response) if (jsonObject.getString("status") == "true") { val dataArray = jsonObject.getJSONArray("data") for (i in 0 until dataArray.length()) { val playersModel = PlayersModel() val dataobj = dataArray.getJSONObject(i) playersModel.setNames(dataobj.getString("name")) playersModel.setCountrys(dataobj.getString("country")) playersModel.setCitys(dataobj.getString("city")) playersModelArrayList.add(playersModel) } } } catch (e: JSONException) { e.printStackTrace() } return playersModelArrayList } }
Diving Deep In Above
Let us see what is MainActivity.kt class is saying to the compiler.
First of all, concentrate on the below snippet
internal var URL = "https://demonuts.com/Demonuts/JsonTest/Tennis/json_parsing.php" private val jsoncode = 1 private var listView: ListView? = null private var playersModelArrayList: ArrayList<PlayersModel>? = null private var customeAdapter: CustomeAdapter? = null
First line is the variable URL which contains the full URL from which we will fetch the JSON data.
Second line is containing one integer value.
Third line is the object of the list view and fourth line is the array list with the objects of the PlayersModel class.
And last line is the object of the CustomAdapter class.
Below is the code for sampleKo() method.
private fun sampleKo() { //https://github.com/androidmads/KotlinFuelHttpSample/blob/master/app/src/main/java/com/androidmads/kotlinfuelhttpsample/MainActivity.kt //https://github.com/kittinunf/Fuel/blob/1.16.0/README.md try { Fuel.post(URL, listOf()).responseJson { request, response, result -> Log.d("plzzzzz", result.get().content) onTaskCompleted(result.get().content) } } catch (e: Exception) { } finally { } }
Here, we are using the fuel library. After making the http request, compiler will execute onTaskCompleted() method.
onTaskCompleted() method has one parameter and we will send the JSON response in this parameter.
Below is the code for onTaskCompleted() method
fun onTaskCompleted(response: String) { Log.d("responsejson", response) playersModelArrayList = getInfo(response) customeAdapter = CustomeAdapter(this, playersModelArrayList!!) listView!!.adapter = customeAdapter }
It will first fill the playersModelArrayList using getInfo() method.
Then it will initialize the adapter using this playersModelArrayList.
And finally, compiler will populate the List view using this adapter.
Following the code for getInfo() method.
fun getInfo(response: String): ArrayList<PlayersModel> { val playersModelArrayList = ArrayList<PlayersModel>() try { val jsonObject = JSONObject(response) if (jsonObject.getString("status") == "true") { val dataArray = jsonObject.getJSONArray("data") for (i in 0 until dataArray.length()) { val playersModel = PlayersModel() val dataobj = dataArray.getJSONObject(i) playersModel.setNames(dataobj.getString("name")) playersModel.setCountrys(dataobj.getString("country")) playersModel.setCitys(dataobj.getString("city")) playersModelArrayList.add(playersModel) } } } catch (e: JSONException) { e.printStackTrace() } return playersModelArrayList }
This method will get the JSON response in the parameter.
Using this JSON response, compiler will fill the playersModelArrayList
Download Code For JSON Kotlin
https://github.com/demonuts/Kotlin-Parse-JSON-From-Url-Android-HTTP-Request