📜  Android 中已弃用的 AsyncTask 的替代方案

📅  最后修改于: 2022-05-13 01:55:06.876000             🧑  作者: Mango

Android 中已弃用的 AsyncTask 的替代方案

Android 中的AsyncTask(异步任务)是一个抽象类,或者更确切地说是一个帮助类,它让应用程序在后台执行繁琐的任务并在前端并行执行 UI 更改。这与 Threading 非常相似,但不构成任何线程框架。可以使用 AsyncTask 执行加载图像、下载音乐、图片、文件等后台任务。但是,现在不推荐使用 AsyncTask,开发人员可能迟早需要为此提供替代方案。

AsyncTask 现在如何出现在 IDE 中

通过本文,我们将向您展示 2 种方法,通过它们您可以执行后台任务并同时更新 UI 元素。两种选择是:

  1. 使用 Executor 和 Handler 的组合
  2. 使用线程

但首先,让我们看看 AsyncTask 是如何工作的。

AsyncTask 通用代码结构

下面的代码实现了一个AsyncTask到一个内部类MyCustomClass 。 AsyncTask 需要三个参数:

  1. 参数:可以是 Int、String 类型,可以是任何作为输入的对象,用于执行假定的任务,当没有输入时为 Void。
  2. 进度:执行任务时发布的单位,不需要时作废。
  3. 结果:可以是 Int、String 类型,任务完成后的任何对象。当不需要输出变量时无效。

关联的成员函数有:



  1. onPreExecute()可选
  2. doInBackground(Params...)必需
  3. onProgressUpdate(Progress…)可选
  4. onPostExecute(Result)可选

下面是实现AsyncTask的基本代码结构。

Kotlin
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 ()
    inner class MyCustomClass: AsyncTask(){
  
        override fun doInBackground(vararg params: String?): String {
            TODO()
        }
  
        override fun onPostExecute(result: String?) {
            TODO()
        }
  
    }
}


Kotlin
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(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(){
  
        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


  
    
  


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


Kotlin
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(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


  
    
  


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


Kotlin
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(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


  
    
  


例子:

现在在这个例子中,我们将一个整数值(输入)传递给任务。在后台将输入转换为String,转换后会显示在TextView中。

科特林

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(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(){
  
        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



  
    
  

输出:

所以基本上,代码工作得很好。但是,我们已经使用AsyncTask来执行我们的任务,它已被弃用,迟早需要替换。

实现 AsyncTask 时的输出

备选方案 1:使用 Executor 和 Handler

下面有一个示例代码。如果您看到,则声明了一个执行程序和一个处理程序。执行器将帮助在后台执行任何任务,处理程序将帮助进行 UI 更改。



科特林

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

例子:

我们使用了与AsyncTask相同的示例。在这里,执行程序将执行任务,一旦获得所需的结果,就会使用处理程序更改 UI。

科特林

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



  
    
  

输出:

代码运行得很好。我们得到了想要的结果。

当我们使用 Executor & Handler 时的输出

备选方案 2:使用线程

下面的代码运行一个线程。标记的注释显示了要进行背景和 UI 更改的代码的位置。使用线程时,任何 UI 更改都必须在 UI 线程内运行,任何后台进程都必须在 UI 线程外运行。

科特林

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

例子:

现在让我们看一个示例,我们将传递一个 Integer 以将其转换为 String 并将其传递给 TextView。

科特林

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



  
    
  

输出:

代码运行得很好。我们有我们想要的结果。

使用 Thread 时的输出

想要一个更快节奏和更具竞争力的环境来学习 Android 的基础知识吗?
单击此处前往由我们的专家精心策划的指南,旨在让您立即做好行业准备!