How to make an API call in Android with Kotlin?
I have heard of Anko . But I want to use methods provided by Kotlin like in Android we have Asynctask for background operations.
How to make an API call in Android with Kotlin?
I have heard of Anko . But I want to use methods provided by Kotlin like in Android we have Asynctask for background operations.
AsyncTask
is an Android API, not a language feature that is provided by Java nor Kotlin. You can just use them like this if you want:
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)
// ...
}
}
Anko's doAsync
is not really 'provided' by Kotlin, since Anko is a library that uses language features from Kotlin to simplify long codes. Check here:
If you use Anko your code will be similar to this:
doAsync {
// ...
}
You can get a similar syntax to Anko's fairly easy. If you just wan't the background task you can do something like
class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg params: Void?): Void? {
handler()
return null
}
}
And use it like
doAsync {
yourTask()
}.execute()
Here is an example that will also allow you to update any UI or progress displayed to the user.
Async Class
class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
init {
execute()
}
override fun doInBackground(vararg params: Void?): Void? {
handler()
return null
}
}
Simple Usage
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)
}
}
link - Github Irontec
I always use this form:
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
}
}
You invoke it in the following way:
loadingProducts = object : LoadingProducts() {
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
Log.e("Result", result)
}
}
loadingProducts.execute()
I use the open so that I can call the onPostExecute
method for the result.
if in the case you want to do it without using Anko and the correct way is to use the following way
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}
}
and the way to execute it is as follows
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 ?: "")
}
}