Создание пользовательского 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.