安卓系统中不推荐使用的 AsyncTask 的替代品
原文:https://www . geesforgeks . org/alternatives-for-the-弃用-asynctask-in-android/
Android 中的 AsyncTask(异步任务)是一个抽象类,或者更确切地说是一个助手类,让应用程序在后台执行繁琐的任务,在前端并行执行 UI 更改。这与线程非常相似,但不构成任何线程框架。后台任务,如加载图像、下载音乐、图片、文件等可以使用 AsyncTask 来执行。然而,AsyncTask 现在已经被弃用,开发人员可能迟早需要一个替代方案。
异步任务现在如何出现在集成开发环境中
通过这篇文章,我们将向您展示 2 种方法,通过它们您可以执行后台任务并同时更新 UI 元素。两种选择是:
- 使用执行器和处理器的组合
- 使用螺纹
但是首先,让我们看看 AsyncTask 是如何工作的。
异步任务通用代码结构
下面的代码将一个异步任务实现到一个内部类我的自定义类。AsyncTask 需要三个参数:
- 参数: 可以是 Int、String 类型,任何作为输入的对象,用于执行假定的任务,当没有输入时无效。
- 进度: 执行任务时发布单位,不需要时作废。
- 结果: 可以是 Int、String 类型,任务完成后可以是任何对象。不需要输出变量时无效。
关联的成员函数有:
- onPreExecute() 可选
- doInBackground(Params…)必选
- on Progress update(Progress…)可选
- onPostExecute(结果) 可选
下面是实现 AsyncTask 的基本代码结构。
我的锅
import android.os.AsyncTask
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
// AsyncTask <Params: Any!, Progress: Any!, Result: Any!>()
inner class MyCustomClass: AsyncTask<String, Void, String>(){
override fun doInBackground(vararg params: String?): String {
TODO()
}
override fun onPostExecute(result: String?) {
TODO()
}
}
}
示例:
在本例中,我们将向任务传递一个整数值(输入)。在后台,输入被转换成字符串,转换后,它将显示在文本视图中。
我的锅
import android.annotation.SuppressLint
import android.os.AsyncTask
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myTextView = findViewById<TextView>(R.id.textView)
val myInput = 100
MyCustomClass(myTextView).execute(myInput)
}
// Input type is Int and Result is a String
@SuppressLint("StaticFieldLeak")
inner class MyCustomClass(var textView: TextView): AsyncTask<Int, Void, String>(){
override fun doInBackground(vararg params: Int?): String {
// Convert the input Params:Int
// to String and return the Result:String
return params[0].toString()
}
// Result:String is set as text in the passed TextView
override fun onPostExecute(result: String?) {
textView.text = result
}
}
}
可扩展标记语言
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
输出:
所以基本上,代码工作得非常好。然而,我们已经使用 AsyncTask 来执行我们的任务,这是不推荐使用的,迟早需要更换。
实现异步任务时的输出
备选方案 1:使用执行器和处理程序
下面是一个示例代码。如果您看到,声明了一个执行器和一个处理程序。执行器将帮助在后台执行任何任务,处理程序将帮助进行用户界面更改。
我的锅
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myExecutor = Executors.newSingleThreadExecutor()
val myHandler = Handler(Looper.getMainLooper())
myExecutor.execute {
// Do something in background (back-end process)
}
myHandler.post {
// Do something in UI (front-end process)
}
}
}
示例:
我们使用了与相同的例子。在这里,执行器将执行任务,一旦获得所需的结果,就使用处理程序对用户界面进行更改。
我的锅
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.TextView
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
private val myExecutor = Executors.newSingleThreadExecutor()
private val myHandler = Handler(Looper.getMainLooper())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myTextView = findViewById<TextView>(R.id.textView)
val myInput = 55
doMyTask(myTextView, myInput)
}
private fun doMyTask(textView: TextView, input: Int){
myExecutor.execute {
val result = input.toString()
myHandler.post {
textView.text = result
}
}
}
}
可扩展标记语言
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
输出:
代码运行得非常好。我们已经得到了预期的结果。
当我们使用执行器和处理器时的输出
备选方案 2:使用线程
下面的代码运行一个线程。标记的注释显示了要进行背景和用户界面更改的代码。使用线程时,任何用户界面更改都必须在用户界面线程内部运行,任何后台进程都必须在用户界面线程外部运行。
我的锅
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Thread(Runnable {
// Do something in Background (Back-end)
runOnUiThread {
// Do something in UI (Front-end)
}
}).start()
}
}
示例:
现在让我们看一个例子,我们将传递一个整数来将其转换为字符串,并将其传递给文本视图。
我的锅
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myTextView = findViewById<TextView>(R.id.textView)
val myInput = 26
doMyTask(myTextView, myInput)
}
private fun doMyTask(textView: TextView, input: Int){
Thread(Runnable {
val result = input.toString()
runOnUiThread {
textView.text = result
}
}).start()
}
}
可扩展标记语言
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"/>
</RelativeLayout>
输出:
代码运行得非常好。我们有我们想要的结果。
使用线程时的输出