Пишем без Retrofit'а, Gson'a и Kotlin Coroutines Android приложение
Порой нам хочется написать код без лишних библиотек, чтобы более глубоко понять основные принципы или просто ради интереса.
В качестве примера я написал простое Android приложение, которое позволяет юзерам найти значение русского слова:
В данном примере GET запрос реализован через встроенные средства Java, которые находятся в пакете java.net.*
Парсинг JSON осуществляется через встроенный в Android пакет org.json.*
А для выполнения запроса на background потоке я использую функции обратного вызова и Java пакет java.util.concurrent.*
Также для поиска реализован Debounce эффект с задержкой в 500 мс.
Ну что ж пройдемся по всем частям более подробно
Делаем GET запрос без Retrofit’а)
Покажу сразу код:
open class GetRequest(private val url: String) {
private val executor = Executors.newSingleThreadExecutor()
private val handler = Handler(Looper.getMainLooper())
fun execute(onSuccess: (json: String) -> Unit, onError: (error: GetError) -> Unit) {
executor.execute {
try {
val connection = URL(url).openConnection() as HttpsURLConnection
connection.requestMethod = "GET"
connection.setRequestProperty("Content-Type", "application/json; utf-8")
connection.connectTimeout = 5000
connection.readTimeout = 5000
val reader = BufferedReader(InputStreamReader(connection.inputStream))
val content = StringBuffer()
var inputLine = reader.readLine()
while (inputLine != null) {
content.append(inputLine)
inputLine = reader.readLine()
}
connection.disconnect()
handler.post { onSuccess(content.toString()) }
} catch (error: Exception) {
handler.post {
if (error is UnknownHostException) {
onError(GetError.MISSING_INTERNET)
} else {
onError(GetError.OTHER)
}
}
}
}
}
}
Мы используем статический метод Executors.newSingleThreadExecutor()
для создания одиночного пула потоков, который мы юзаем, чтобы выполнить наш запрос в background потоке.
Handler
используется для возвращения результата на UI поток
HttpsURLConnection
входит во встроенный пакет java.net.*
и предназначен для выполнения сетевых запросов.
Параметры HttpsURLConnection
я думаю вам понятны.
Затем мы читаем все данные через BufferedReader
и отправляем результат дальше через функции обратного вызова, которые передаются в метод execute()
.
Обратите внимание, наш класс может иметь наследников.
В моем тестовом приложении это DictGetRequest:
class DictGetRequest(word: String) :
GetRequest("https://api.dictionaryapi.dev/api/v2/entries/ru/$word")