是的,回调的概念在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
}
};
这将与上面使用单独侦听器接口的实现一样好,但是这存在一些问题:
首先,你实际上可以打破一切。这一切都归结为上面的电话。如果您作为开发人员覆盖了上述内容,并且忘记包含超级调用或简单地将其删除,则无论出于何种原因,都不会再调用中的原始方法。例如,带有 的整个侦听器实现将突然不再工作,因为对回调的调用是在 中实现的。您还可以通过不知不觉或不知不觉地影响状态来以许多其他方式打破它,因此它将不再起作用。ExampleTask
super.onPostExecute()
onPostExecute()
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
- 每个类都必须在适当和预期的位置提供侦听器实现。当然,您可以稍后通过覆盖来添加它们,但这总是非常危险的。即使@flup拥有13k的声誉也忘记了在回答中包含呼叫,想象一下其他一些不有经验的开发人员可能会做什么!
onPostExecute()
super.onPostExecute()
- 一点点的抽象从来不会伤害任何人。编写特定的侦听器可能稍微多一些代码,但这是一个更好的解决方案。代码将更清晰,更具可读性,更易于维护。使用像覆盖这样的快捷方式基本上牺牲了代码质量,以获得一点便利。从长远来看,这绝不是一个好主意,只会造成问题。
onPostExecute()