Kotlin ListView with custom BaseAdapter and API integration
Create Custom ListView with BaseAdapter
ListView Layout (‘res/layouts/layout_list_view.xml’)
This is the base Layout of what will later fill the ListView with Items.
<?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:orientation="vertical">
<TextView
android:id="@+id/text_view_item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textColor="#FF000000"/>
<TextView
android:id="@+id/text_view_item_description"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Main Layout (‘res/layouts/activity_main.xml’)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/listy"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Item.kt Class
Item Objects will be the used to fill up the List with Data.
class Item(val itemName: String, val itemDescription: String) {
override fun toString(): String {
return this.itemName
}
}
Adapter.kt Class
This implements the Adapter Interface (BaseAdapter) so that we can access and edit our ListView and fill it with our own custom Item Objects.
class CustomListAdapter(context: Context, items: ArrayList<Item>) : BaseAdapter() {
private val context: Context
private val items: ArrayList<Item>
override fun getCount(): Int {
return items.size //returns total of items in the list
}
override fun getItem(position: Int): Any {
return items[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent:ViewGroup?):
View? {
var convertView: View? = convertView
if (convertView == null) {
convertView = LayoutInflater.from(context)
.inflate(R.layout.layout_list_view, parent, false)
} val currentItem = getItem(position) as Item val textViewItemName = convertView
?.findViewById(R.id.text_view_item_name) as TextViewval textViewItemDescription = convertView
?.findViewById(R.id.text_view_item_description) as TextView textViewItemName.text = currentItem.itemName
textViewItemDescription.text = currentItem.itemDescription return convertView
} init {
this.context = context
this.items = items
}
}
ListView Example Usage in MainActivity.kt
val data = generateItems() // calls function to get items listval adapter = CustomListAdapter(this@MainActivity, data)val itemsListView: ListView = findViewById<View>(R.id.listy) as ListView
itemsListView.setAdapter(adapter)// OnClick Event that will display the Name of the Item in a toast
itemsListView.setOnItemClickListener { parent, view, position, id ->
val element = adapter.getItem(position)
toast(element.toString())
}
Get Random Names from API
randommer.io is an API for random Data. Creating an account is free and the requests are simple with short responses.
This is an example request to get a random first- and last name:
curl -X GET "https://randommer.io/api/Name?nameType=fullname&quantity=1" -H "accept: */*" -H "X-Api-Key: {YOU_API_KEY}"
Make a Request to the API
To make requests in Kotlin we will use OkHttp.
Install OkHttp
build.gradle:
dependencies {
//...
implementation 'com.squareup.okhttp3:okhttp:3.8.1'
}
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
Get API Data
To get data from our API we will create a function which gets a certain number of Names, parses the request result and returns it as a List of Strings.
In MainActivity.kt:
fun getNamesData(num: Int) : List<String> {
val apiUrlFullName = "https://randommer.io/api/Name?nameType=fullname&quantity=" + num
val request = Request.Builder()
.url(apiUrlFullName)
.header("accept", "*/*")
.header("X-Api-Key", "{YOU_API_KEY}")
.build()
val response = client.newCall(request).execute()
return response.body()?.string()?.replace("[", "")
?.replace("]", "")
?.replace("\"","")
?.split(",")!!
}
Async Request and Display Result in ListView
To make a requests in an application it is generally required to do it async so that it wont block the main thread. For that reason we will use Anko for Kotlin which makes it fairly easy.
Install Anko
build.gradle:
dependencies {
//...
implementation 'org.jetbrains.anko:anko-common:0.9'
}
Make async Request and display Result in ListView
To finish the app up the final challenge is to implement and execute an async request and display the received Data in the ListView.
In MainActivity.kt:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
doAsync {
// get Data from API
val namesData = getNamesData(50)
val listy = ArrayList<Item>()
namesData.forEach {
listy.add(Item(it, "Just a regular Person..."))
}uiThread {
// instantiate the custom list adapter
val adapter = CustomListAdapter(this@MainActivity, listy)// get the ListView and attach the adapter
val itemsListView: ListView = findViewById<View>(R.id.listy) as ListView
itemsListView.setAdapter(adapter)
itemsListView.setOnItemClickListener { parent, view, position, id ->
val element = adapter.getItem(position)
toast(element.toString())
}
}
}
}
Conclusion
As you can see it is fairly easy to create an app in Kotlin that receives and displays data from an API. This is meant to help everyone who wants a quick and easy way to communicate with an API.