Xaver Kapell..
46
是的,回调的概念在Java中也非常存在.在Java中,您可以像这样定义一个回调:
public interface TaskListener {
public void onFinished(String result);
}
人们通常会将这些类型的侦听器定义嵌套在AsyncTask这样的内容中:
public class ExampleTask extends AsyncTask {
public interface TaskListener {
public void onFinished(String result);
}
...
}
并且在回调中的完整实现AsyncTask将如下所示:
public class ExampleTask extends AsyncTask {
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
}
}
所有这些都隐藏在称为匿名类的语言功能之后.突然重写这样的方法似乎不那么干净和快速了吗?
总结一下:
覆盖这样的方法实际上会创建一个新的子类.你不只是添加一个回调,你正在修改这个类的工作方式,并且可以在不知不觉中破坏这么多东西.
像这样的调试错误不仅仅是a**的痛苦.因为没有明显的原因突然之间ExampleTask可能会抛出Exceptions或根本不再工作,因为你从未真正修改过它的代码.
每个类都必须在适当和有意的地方提供监听器实现.当然,您可以稍后通过覆盖添加它们,onPostExecute()但这总是非常危险.即使是拥有13k声望的@flup也忘了super.onPostExecute()在他的回答中包含这个电话,想象一下其他一些不像经验丰富的开发者可能做的事情!
一点抽象从不伤害任何人.编写特定的侦听器可能会稍微多一些代码,但它是一个更好的解决方案.代码将更清晰,更易读,更易于维护.使用像覆盖这样的快捷方式onPostExecute()基本上牺牲了代码质量,以方便一点.从来没有一个好主意,只会造成问题.