AsyncTask dans Android avec Kotlin
Comment faire un appel API dans Android avec Kotlin?
J'ai entendu parler de Anko . Mais je veux utiliser les méthodes fournies par Kotlin, comme dans Android, nous avons Asynctask pour les opérations en arrière-plan.
AsyncTask
est un Android API, pas une fonctionnalité language fournie par Java ni Kotlin. Vous pouvez simplement les utiliser comme ceci si vous voulez:
class someTask() : AsyncTask<Void, Void, String>() {
override fun doInBackground(vararg params: Void?): String? {
// ...
}
override fun onPreExecute() {
super.onPreExecute()
// ...
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
// ...
}
}
La variable doAsync
d'Anko n'est pas vraiment "fournie" par Kotlin, car Anko est une bibliothèque qui utilise les fonctionnalités de langage de Kotlin pour simplifier les codes longs. Vérifier ici:
Si vous utilisez Anko, votre code sera similaire à ceci:
doAsync {
// ...
}
Vous pouvez obtenir une syntaxe similaire à celle d'Anko, assez facile. Si vous ne voulez pas que la tâche de fond, vous pouvez faire quelque chose comme
class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg params: Void?): Void? {
handler()
return null
}
}
Et l'utiliser comme
doAsync {
yourTask()
}.execute()
Voici un exemple qui vous permettra également de mettre à jour toute interface utilisateur ou toute progression affichée à l'utilisateur.
Classe Async
class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
init {
execute()
}
override fun doInBackground(vararg params: Void?): Void? {
handler()
return null
}
}
Utilisation simple
doAsync {
// do work here ...
myView.post({
// update UI of myView ...
})
}
package com.irontec.kotlintest
import Android.os.AsyncTask
import Android.os.Bundle
import Android.support.v7.app.AppCompatActivity
import Android.view.Menu
import Android.view.MenuItem
import Android.widget.TextView
import kotlinx.Android.synthetic.main.activity_main.*
import org.json.JSONObject
import Java.io.BufferedInputStream
import Java.io.BufferedReader
import Java.io.InputStreamReader
import Java.net.HttpURLConnection
import Java.net.URL
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
GetWeatherTask(this.text).execute()
}
class GetWeatherTask(textView: TextView) : AsyncTask<Unit, Unit, String>() {
val innerTextView: TextView? = textView
override fun doInBackground(vararg params: Unit?): String? {
val url = URL("https://raw.githubusercontent.com/irontec/Android-kotlin-samples/master/common-data/bilbao.json")
val httpClient = url.openConnection() as HttpURLConnection
if (httpClient.responseCode == HttpURLConnection.HTTP_OK) {
try {
val stream = BufferedInputStream(httpClient.inputStream)
val data: String = readStream(inputStream = stream)
return data
} catch (e: Exception) {
e.printStackTrace()
} finally {
httpClient.disconnect()
}
} else {
println("ERROR ${httpClient.responseCode}")
}
return null
}
fun readStream(inputStream: BufferedInputStream): String {
val bufferedReader = BufferedReader(InputStreamReader(inputStream))
val stringBuilder = StringBuilder()
bufferedReader.forEachLine { stringBuilder.append(it) }
return stringBuilder.toString()
}
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
innerTextView?.text = JSONObject(result).toString()
/**
* ... Work with the weather data
*/
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
val id = item.itemId
if (id == R.id.action_settings) {
return true
}
return super.onOptionsItemSelected(item)
}
}
lien - Github Irontec
J'utilise toujours ce formulaire:
open class LoadingProducts : AsyncTask<Void, Void, String>() {
private var name = ""
override fun doInBackground(vararg p0: Void?): String {
for (i in 1..100000000) {
if (i == 100000000) {
name = "Hello World"
}
}
return name
}
}
Vous l'invoquez de la manière suivante:
loadingProducts = object : LoadingProducts() {
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
Log.e("Result", result)
}
}
loadingProducts.execute()
J'utilise open pour pouvoir appeler la méthode onPostExecute
comme résultat.
si dans le cas où vous voulez le faire sans utiliser Anko et la bonne façon est d'utiliser la manière suivante
open class PromotionAsyncTask : AsyncTask<JsonArray, Void, MutableList<String>>() {
private lateinit var out: FileOutputStream
private lateinit var bitmap: Bitmap
private lateinit var directory: File
private var listPromotion: MutableList<String> = mutableListOf()
override fun doInBackground(vararg params: JsonArray?): MutableList<String> {
directory = Environment.getExternalStoragePublicDirectory("Tambo")
if (!directory.exists()) {
directory.mkdirs()
}
for (x in listFilesPromotion(params[0]!!)) {
bitmap = BitmapFactory.decodeStream(URL(x.url).content as InputStream)
out = FileOutputStream(File(directory, "${x.name}"))
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out)
out.flush()
out.close()
listPromotion.add(File(directory, "${x.name}").toString())
}
return listPromotion
}
private fun listFilesPromotion(jsonArray: JsonArray): MutableList<Promotion> {
var listString = mutableListOf<Promotion>()
for (x in jsonArray) {
listString.add(Promotion(x.asJsonObject.get("photo")
.asString.replace("files/promos/", "")
, "https://tambomas.pe/${x.asJsonObject.get("photo").asString}"))
}
return listString}
}
et la façon de l'exécuter est la suivante
promotionAsyncTask = object : PromotionAsyncTask() {
override fun onPostExecute(result: MutableList<String>?) {
super.onPostExecute(result)
listFile = result!!
contentLayout.visibility = View.VISIBLE
progressLottie.visibility = View.GONE
}
}
promotionAsyncTask.execute(response!!.body()!!.asJsonObject.get("promos").asJsonArray)