gpt4 book ai didi

java - Android:将函数引用传递给 AsyncTask

转载 作者:IT老高 更新时间:2023-10-28 23:38:12 24 4
gpt4 key购买 nike

我是 android 新手,非常习惯于 web 开发。在 javascript 中,当您想要执行异步任务时,您将函数作为参数(回调)传递:

http.get('www.example.com' , function(response){
//some code to handle response
});

我想知道我们是否可以对 android 的 AsyncTask 做同样的事情,将函数引用传递给 onPostExecute() 方法,它就会运行它。

有什么建议吗?

最佳答案

是的,回调的概念在 Java 中也很常见。在 Java 中,您可以这样定义回调:

public interface TaskListener {
public void onFinished(String result);
}

人们通常会在 AsyncTask 中嵌套此类监听器定义。像这样:

public class ExampleTask extends AsyncTask<Void, Void, String> {

public interface TaskListener {
public void onFinished(String result);
}

...
}

以及 AsyncTask 中回调的完整实现看起来像这样:

public class ExampleTask extends AsyncTask<Void, Void, String> {

public interface TaskListener {
public void onFinished(String result);
}

// This is the reference to the associated listener
private final TaskListener taskListener;

public ExampleTask(TaskListener listener) {
// The listener reference is passed in through the constructor
this.taskListener = listener;
}

@Override
protected String doInBackground(Void... params) {
return doSomething();
}

@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);

// In onPostExecute we check if the listener is valid
if(this.taskListener != null) {

// And if it is we call the callback function on it.
this.taskListener.onFinished(result);
}
}
}

onPostExecute()后台任务完成后立即调用。你可以像这样使用整个东西:

ExampleTask task = new ExampleTask(new ExampleTask.TaskListener() {
@Override
public void onFinished(String result) {
// Do Something after the task has finished
}
});

task.execute();

或者您可以定义 TaskListener像这样完全分开:

ExampleTask.TaskListener listener = new ExampleTask.TaskListener() {
@Override
public void onFinished(String result) {
// Do Something after the task has finished
}
};

ExampleTask task = new ExampleTask(listener);
task.execute();

或者你可以继承 TaskListener像这样:

public class ExampleTaskListener implements TaskListener {

@Override
public void onFinished(String result) {

}
}

然后像这样使用它:

ExampleTask task = new ExampleTask(new ExampleTaskListener());    
task.execute();

您当然可以直接覆盖 onPostExecute() AsyncTask 的方法,但不建议这样做,而且在大多数情况下实际上是非常糟糕的做法。例如,您可以这样做:

ExampleTask task = new ExampleTask() {
@Override
public void onPostExecute(String result) {
super.onPostExecute(result);

// Your code goes here
}
};

这将与上面使用单独的监听器接口(interface)的实现一样有效,但存在一些问题:

首先你可以真正打破ExampleTask全部一起。这一切都归结为super.onPostExecute()调用上面。如果您作为开发人员覆盖 onPostExecute()像上面一样忘记包含 super 调用,或者出于任何原因将其删除,原始 onPostExecute() ExampleTask 中的方法将不再被调用。例如,使用 TaskListener 的整个监听器实现由于对回调的调用是在 onPostExecute() 中实现的,因此会突然不再工作。 .你也可以打破TaskListener在许多其他方面通过在不知不觉中或无意中影响 ExampleTask 的状态所以它不再起作用了。

如果您在重写这样的方法时查看实际发生的情况,就会更清楚发生了什么。通过覆盖 onPostExecute()您正在创建 ExampleTask 的新子类.这与执行此操作完全相同:

public class AnotherExampleTask extends ExampleTask {

@Override
public void onPostExecute(String result) {
super.onPostExecute(result);

// Your code goes here
}
}

所有这些都隐藏在称为匿名类的语言功能后面。突然覆盖这样的方法似乎不再那么干净和快速了,是吗?

总结:

  • 重写这样的方法实际上会创建一个新的子类。您不仅添加了回调,还修改了此类的工作方式,并且可能会在不知不觉中破坏很多东西。
  • 调试这样的错误可能不仅仅是一个痛苦的问题。因为突然ExampleTask可以抛出Exceptions或者只是没有明显的原因不再工作,因为你从未真正修改过它的代码。
  • 每个类都必须在合适的地方提供监听器实现。当然,您可以稍后通过覆盖 onPostExecute() 来添加它们。但这总是非常危险的。甚至拥有 13k 名声的 @flup 也忘记了包含 super.onPostExecute()调用他的答案,想象一下其他没有经验的开发人员可能会做什么!
  • 一点抽象永远不会伤害任何人。编写特定的监听器可能需要更多的代码,但这是一个更好的解决方案。代码将更干净、更易读、更易于维护。使用诸如覆盖 onPostExecute() 之类的快捷方式本质上为了一点方便而牺牲了代码质量。这绝不是一个好主意,从长远来看只会导致问题。

关于java - Android:将函数引用传递给 AsyncTask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26202568/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com