AsyncTask в Android с Котлином

Как сделать вызов API в Android с помощью Kotlin?

Я слышал о Анко . Но я хочу использовать методы, предоставляемые Kotlin, как в Android, у нас есть Asynctask для фоновых операций.

7 ответов


AsyncTask является Android API, а не языка это предусмотрено Java nor Kotlin. Вы можете просто использовать их так, если хотите:

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)
        // ...
    }
}
Анко!--3--> на самом деле не "предоставляется" Котлином, так как Anko-это библиотека, которая использует языковые функции из Котлина для упрощения длинных кодов. Проверять здесь:

если вы используете Anko, ваш код будет похож на это:

doAsync {
    // ...
}

вы можете получить аналогичный синтаксис для Anko довольно легко. Если вы просто не хотите фоновую задачу, вы можете сделать что-то вроде

class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
    override fun doInBackground(vararg params: Void?): Void? {
        handler()
        return null
    }
}

и использовать его как

doAsync {
    yourTask()
}.execute()

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

ссылка - Github Irontec


вот пример, который также позволит вам обновить любой пользовательский интерфейс или прогресс, отображаемый пользователю.

Асинхронный Класс

class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
    init {
        execute()
    }

    override fun doInBackground(vararg params: Void?): Void? {
        handler()
        return null
    }
}

Простота Использования

doAsync {
    // do work here ...

    myView.post({
        // update UI of myView ...
    })
}

Я всегда использую эту форму:

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

вы вызываете его следующим образом:

loadingProducts = object : LoadingProducts() {
        override fun onPostExecute(result: String?) {
            super.onPostExecute(result)

            Log.e("Result", result)
        }
    }

loadingProducts.execute()

Я использую open, чтобы я мог вызвать onPostExecute метод для результата.


Если в случае, если вы хотите сделать это без использования Anko, и правильный способ-использовать следующий способ

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

и способ его выполнения выглядит следующим образом

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)

  private fun updateUI(account: GoogleSignInAccount?) {
    if (account != null) {
        try {
            AsyncTaskExample().execute()
        } catch (e: Exception) {
        }
    }
}
inner class AsyncTaskExample : AsyncTask<String, String, String>() {

            override fun onPreExecute() {
                super.onPreExecute()

            }

            override fun doInBackground(vararg p0: String?): String {

                var Result: String = "";
                try {
                    googleToken = GoogleAuthUtil.getToken(activity, accountVal, "oauth2:https://www.googleapis.com/auth/userinfo.profile")
                    signOut()
                } catch (e: Exception) {
                    signOut()
                }


                signOut()

                return Result
            }

            override fun onPostExecute(result: String?) {
                super.onPostExecute(result)
                socialPrsenter.setDataToHitApiGoogleLogin(googleToken ?: "")

            }
        }