Android:将函数引用传递给AsyncTask [英] Android: pass function reference to AsyncTask

查看:83
本文介绍了Android:将函数引用传递给AsyncTask的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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) {

    }
}

然后像使用它一样这个:

And then use it like this:

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






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


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?

总结:


  • 覆盖这样的方法实际上会创建一个新的子类。你不只是添加一个回调,你正在修改这个类的工作方式,并且可以在不知不觉中破坏这么多东西。

  • 这样的调试错误不仅仅是一个痛苦的问题。 **。因为突然 ExampleTask 可能会抛出异常或者根本没有明显的原因不再工作,因为你从未真正修改过它的代码。

  • 每个类都必须在适当和有意的地方提供侦听器实现。当然你可以稍后通过重写 onPostExecute()来添加它们,但这总是非常危险。即使是@flup,他的13k声誉已经忘记在他的回答中包含 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 throw Exceptions 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 the super.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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆