如何使用Kotlin在Android中进行API调用?
我听说过Anko.但我想使用Kotlin提供的方法,就像在Android中我们有Asynctask进行后台操作.
shi*_*psh 51
AsyncTask是一个Android API,而不是Java和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)
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
Anko doAsync并不是由Kotlin"提供",因为Anko是一个使用Kotlin语言功能来简化长码的库.点击这里:
如果您使用Anko,您的代码将类似于:
doAsync {
// ...
}
Run Code Online (Sandbox Code Playgroud)
Alg*_*gar 28
您可以很容易地获得与Anko类似的语法.如果你只是做背景任务,你可以做类似的事情
class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
override fun doInBackground(vararg params: Void?): Void? {
handler()
return null
}
}
Run Code Online (Sandbox Code Playgroud)
并使用它
doAsync {
yourTask()
}.execute()
Run Code Online (Sandbox Code Playgroud)
que*_*ful 12
这是一个示例,它还允许您更新显示给用户的任何UI或进度.
异步类
class doAsync(val handler: () -> Unit) : AsyncTask<Void, Void, Void>() {
init {
execute()
}
override fun doInBackground(vararg params: Void?): Void? {
handler()
return null
}
}
Run Code Online (Sandbox Code Playgroud)
简单用法
doAsync {
// do work here ...
myView.post({
// update UI of myView ...
})
}
Run Code Online (Sandbox Code Playgroud)
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)
}
}
Run Code Online (Sandbox Code Playgroud)
AsyncTask在 API 级别 30 中已弃用。为了实现类似的行为,我们可以使用Kotlin 并发实用程序(协程)。
在 上创建扩展函数CoroutineScope:
fun <R> CoroutineScope.executeAsyncTask(
onPreExecute: () -> Unit,
doInBackground: () -> R,
onPostExecute: (R) -> Unit
) = launch {
onPreExecute()
val result = withContext(Dispatchers.IO) { // runs in background thread without blocking the Main Thread
doInBackground()
}
onPostExecute(result)
}
Run Code Online (Sandbox Code Playgroud)
现在它可以用于任何CoroutineScope实例,例如,在ViewModel:
class MyViewModel : ViewModel() {
fun someFun() {
viewModelScope.executeAsyncTask(onPreExecute = {
// ...
}, doInBackground = {
// ...
"Result" // send data to "onPostExecute"
}, onPostExecute = {
// ... here "it" is a data returned from "doInBackground"
})
}
}
Run Code Online (Sandbox Code Playgroud)
或在Activity/ Fragment:
lifecycleScope.executeAsyncTask(onPreExecute = {
// ...
}, doInBackground = {
// ...
"Result" // send data to "onPostExecute"
}, onPostExecute = {
// ... here "it" is a data returned from "doInBackground"
})
Run Code Online (Sandbox Code Playgroud)
要在应用程序的build.gradle文件的依赖项中使用viewModelScope或lifecycleScope添加下一行:
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION" // for viewModelScope
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$LIFECYCLE_VERSION" // for lifecycleScope
Run Code Online (Sandbox Code Playgroud)
这就是我在项目中避免内存泄漏的做法:
我创建了一个abstract base Async Task用于异步加载的类
import android.os.AsyncTask
abstract class BaseAsyncTask(private val listener: ProgressListener) : AsyncTask<Void, Void, String?>() {
interface ProgressListener {
// callback for start
fun onStarted()
// callback on success
fun onCompleted()
// callback on error
fun onError(errorMessage: String?)
}
override fun onPreExecute() {
listener.onStarted()
}
override fun onPostExecute(errorMessage: String?) {
super.onPostExecute(errorMessage)
if (null != errorMessage) {
listener.onError(errorMessage)
} else {
listener.onCompleted()
}
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
现在,每次我必须在后台执行某些任务时,我都会创建一个新任务LoaderClass并使用我的类对其进行扩展,BaseAsyncTask如下所示:
class LoadMediaTask(listener: ProgressListener) : BaseAsyncTask(listener) {
override fun doInBackground(vararg params: Void?): String? {
return VideoMediaProvider().allVideos
}
}
Run Code Online (Sandbox Code Playgroud)
AsyncLoader现在您可以在应用程序中的任何位置使用新类。
下面是显示/隐藏进度条和处理错误/成功场景的示例:
LoadMediaTask(object : BaseAsyncTask.ProgressListener {
override fun onStarted() {
//Show Progrss Bar
loadingBar.visibility = View.VISIBLE
}
override fun onCompleted() {
// hide progress bar
loadingBar.visibility = View.GONE
// update UI on SUCCESS
setUpUI()
}
override fun onError(errorMessage: String?) {
// hide progress bar
loadingBar.visibility = View.GONE
// Update UI on ERROR
Toast.makeText(context, "No Videos Found", Toast.LENGTH_SHORT).show()
}
}).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
52327 次 |
| 最近记录: |