Создание пользовательского ListView с помощью BaseAdapter

Макет ListView (‘res/layouts/layout_list_view.xml’)

Это базовый макет того, что позже заполнит ListView элементами.

<?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>

Основной макет (‘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

Объекты Item будут использоваться для заполнения списка данными.

class Item(val itemName: String, val itemDescription: String) {  
    override fun toString(): String {  
        return this.itemName  
 }  
}

Класс Adapter.kt

Это реализует интерфейс адаптера (BaseAdapter), чтобы мы могли получать доступ и редактировать наш ListView и заполнять его нашими собственными пользовательскими объектами элементов.

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 TextView
val 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 в MainActivity.kt

val data = generateItems() // calls function to get items list
val 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())  
}

Получить случайные имена из API

randommer.io — это API для случайных данных. Создание учетной записи бесплатно, а запросы простые с короткими ответами.

Это пример запроса на получение случайного имени и фамилии:

curl -X GET "https://randommer.io/api/Name?nameType=fullname&quantity=1" -H  "accept: */*" -H  "X-Api-Key: {YOU_API_KEY}"

Сделать запрос к API

Для выполнения запросов в Kotlin будем использовать OkHttp.

Установить OkHttp

build.gradle:

dependencies {
    //...
    implementation 'com.squareup.okhttp3:okhttp:3.8.1'
}

AndroidManifest.xml

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

Получить данные API

Чтобы получить данные из нашего API, мы создадим функцию, которая получает определенное количество имен, анализирует результат запроса и возвращает его в виде списка строк.

В 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(",")!!  
}

Асинхронный запрос и отображение результата в ListView

Чтобы делать запросы в приложении, обычно требуется делать это асинхронно, чтобы оно не блокировало основной поток. По этой причине мы будем использовать Anko для Kotlin, что делает его довольно простым.

Установить Анко

build.gradle:

dependencies {
    //...
 implementation 'org.jetbrains.anko:anko-common:0.9'
}

Сделать асинхронный запрос и отобразить результат в ListView

Чтобы завершить приложение, последней задачей является реализация и выполнение асинхронного запроса и отображение полученных данных в ListView.

В 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())  
   } 
  }
 }
}

Вывод

Как видите, на Kotlin довольно легко создать приложение, которое получает и отображает данные из API. Это должно помочь всем, кто хочет быстро и легко общаться с API.