问题描述
我是 android 新手,非常习惯网络开发.在 javascript 中,当您想执行异步任务时,您可以将函数作为参数(回调)传递:
I'm new to android and very used to web developing. in javascript when you want to perform an asynchronous task you pass a function as an argument (a callback):
http.get('www.example.com' , function(response){
//some code to handle response
});
我想知道我们是否可以对 android 的 AsyncTask
做同样的事情,将函数引用传递给 onPostExecute()
方法,然后它就会运行它.
I was wondering if we can do the same with android's AsyncTask
, pass a function reference to the onPostExecute()
method , and it will run it.
有什么建议吗?
推荐答案
是的,Java 中也大量存在回调的概念.在 Java 中,您可以像这样定义回调:
Yes the concept of callbacks also very much exists in Java. In Java you define a callback like this:
public interface TaskListener {
public void onFinished(String result);
}
人们通常会像这样将这些类型的侦听器定义嵌套在 AsyncTask
中:
One would often nest these kind of listener definitions inside the AsyncTask
like this:
public class ExampleTask extends AsyncTask<Void, Void, String> {
public interface TaskListener {
public void onFinished(String result);
}
...
}
AsyncTask
中回调的完整实现如下所示:
And a complete implementation of the callback in the AsyncTask
would look like this:
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()
在后台任务完成后立即调用.你可以像这样使用整个东西:
onPostExecute()
is called as soon as the background task finishes. You can use the whole thing like this:
ExampleTask task = new ExampleTask(new ExampleTask.TaskListener() {
@Override
public void onFinished(String result) {
// Do Something after the task has finished
}
});
task.execute();
或者你可以像这样完全单独定义TaskListener
:
Or you can define the TaskListener
completely separately like this:
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
:
Or you can subclass TaskListener
like this:
public class ExampleTaskListener implements TaskListener {
@Override
public void onFinished(String result) {
}
}
然后像这样使用它:
ExampleTask task = new ExampleTask(new ExampleTaskListener());
task.execute();
<小时>
您当然可以只覆盖 AsyncTask
的 onPostExecute()
方法,但不推荐这样做,而且在大多数情况下实际上是非常糟糕的做法.例如,您可以这样做:
You can of course just override the onPostExecute()
method of the AsyncTask
, but that is not recommended and in most cases actually pretty bad practice. For example you could do this:
ExampleTask task = new ExampleTask() {
@Override
public void onPostExecute(String result) {
super.onPostExecute(result);
// Your code goes here
}
};
这将与上面使用单独侦听器接口的实现一样有效,但存在一些问题:
This will work just as well as the implementation above with a separate listener interface, but there are a few problems with this:
首先,您实际上可以将 ExampleTask
全部分解.这一切都归结为上面的 super.onPostExecute()
调用.如果您作为开发人员覆盖了上面的 onPostExecute()
并且忘记包含超级调用,或者出于任何原因将其删除,原始 onPostExecute()
方法在 >ExampleTask
将不再被调用.例如,带有 TaskListener
的整个侦听器实现将突然不再起作用,因为对回调的调用是在 onPostExecute()
中实现的.您还可以通过不知不觉或不知不觉地影响 ExampleTask
的状态以许多其他方式破坏 TaskListener
,使其不再工作.
First and foremost you can actually break the ExampleTask
all together. It all comes down to the super.onPostExecute()
call above. If you as a developer override onPostExecute()
like above and forget to include the super call or simply delete it for whatever reason that the original onPostExecute()
method in the ExampleTask
will not be called anymore. For example the whole listener implementation with the TaskListener
would suddenly not work anymore since the call to the callback is implemented in onPostExecute()
. You can also break the TaskListener
in many other ways by unknowingly or unwittingly influencing the state of the ExampleTask
so it won't work anymore.
如果你看看当你重写这样的方法时实际发生了什么,那么发生的事情就会变得更加清楚.通过覆盖 onPostExecute()
,您正在创建 ExampleTask
的新子类.这将与执行此操作完全相同:
If you look at what's actually happening when you override a method like this than it becomes much more clear what's going on. By overriding onPostExecute()
you are creating a new subclass of ExampleTask
. It would be the exact same thing as doing this:
public class AnotherExampleTask extends ExampleTask {
@Override
public void onPostExecute(String result) {
super.onPostExecute(result);
// Your code goes here
}
}
所有这些都隐藏在称为匿名类的语言功能后面.突然覆盖这样的方法似乎不再那么干净和快速了,是吗?
All this is just hidden behind a language feature called anonymous classes. Suddenly overriding a method like this doesn't seem so clean and quick anymore does it?
总结:
- 重写这样的方法实际上会创建一个新的子类.你不仅仅是添加一个回调,你正在修改这个类的工作方式,并且可能会在不知不觉中破坏很多东西.
- 调试像这样的错误不仅仅是在 a** 中的痛苦.因为突然
ExampleTask
可能会抛出Exceptions
或者只是无缘无故地不再工作,因为你从未真正修改过它的代码. - 每个类都必须在适当和预期的位置提供侦听器实现.当然,您可以稍后通过覆盖
onPostExecute()
来添加它们,但这总是非常危险的.甚至拥有 13k 声誉的 @flup 也忘记在他的回答中包含super.onPostExecute()
调用,想象一下其他一些没有经验的开发人员可能会做什么! - 一点点抽象永远不会伤害任何人.编写特定的侦听器可能会稍微多一些代码,但这是一个更好的解决方案.代码将更清晰、更易读且更易于维护.使用像覆盖
onPostExecute()
这样的快捷方式本质上会牺牲代码质量来获得一点便利.这绝不是一个好主意,从长远来看只会引起问题.
- Overriding a method like this actually creates a new subclass. You are not just adding a callback, you are modifying how this class works and can unknowingly break oh so many things.
- Debugging errors like this can be much more than just a pain in the a**. Because suddenly
ExampleTask
could throwExceptions
or simply not work anymore for no apparent reason, because you never actually modified its code. - Each class has to provide listener implementations at places where it is appropriate and intended. Sure you can just add them later on by overriding
onPostExecute()
but that is always very dangerous. Even @flup with his 13k reputation has forgotten to include thesuper.onPostExecute()
call in his answer, imagine what some other not as experienced developer might do! - A little abstraction never hurt anybody. Writing specific listeners might be slightly more code, but it is a much better solution. The code will be cleaner, more readable and a lot more maintainable. Using shortcuts like overriding
onPostExecute()
essentially sacrifices code quality for a little bit convenience. That is never a good idea an will just cause problems in the long run.
这篇关于Android:将函数引用传递给 AsyncTask的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!