如何将变量传入和传出 AsyncTasks? [英] How to pass variables in and out of AsyncTasks?

查看:13
本文介绍了如何将变量传入和传出 AsyncTasks?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有花太多时间在 Android 中使用 AsyncTasks.我试图了解如何将变量传入和传出类.语法:

I haven't spent much time working with AsyncTasks in Android. I'm trying to understand how to pass variables to and from the class. The syntax:

class MyTask extends AsyncTask<String, Void, Bitmap>{

     // Your Async code will be here

}

它与 < 有点混淆.> 语法在类定义的末尾.以前从未见过这种类型的语法.似乎我只能将一个值传递给 AsyncTask.我的假设不正确吗?如果我还有更多要通过,我该怎么做?

it's a little bit confusing with the < > syntax on the end of the class definition. Never seen that type of syntax before. It seems like I'm limited to only passing one value into the AsyncTask. Am I incorrect in assuming this? If I have more to pass, how do I do that?

另外,我如何从 AsyncTask 返回值?

这是一个类,当你想使用它时,你调用 new MyTask().execute() 但你在类中使用的实际方法是 doInBackground().那么你实际上在哪里返回一些东西?

It's a class and when you want to use it you call new MyTask().execute() but the actual method you use in the class is doInBackground(). So where do you actually return something?

推荐答案

注意:以下所有信息都可以在 Android 开发者处获得 AsyncTask 参考页.Usage 标头有一个示例.另请查看 无痛线程 Android 开发者博客条目.

Note: all of the information below is available on the Android Developers AsyncTask reference page. The Usage header has an example. Also take a look at the Painless Threading Android Developers Blog Entry.

看看AsynTask 的源代码.

有趣的<代码><> 表示法允许您自定义异步任务.括号用于帮助实现Java 中的泛型.

The funny < > notation lets you customize your Async task. The brackets are used to help implement generics in Java.

您可以自定义任务的 3 个重要部分:

There are 3 important parts of a task you can customize:

  1. 传入的参数类型 - 您想要的任何数字
  2. 用于更新进度条/指示器的类型
  3. 后台任务完成后返回的类型

请记住,以上任何一个都可能是接口.这就是您可以在同一个调用中传入多种类型的方法!

And remember, that any of the above may be interfaces. This is how you can pass in multiple types on the same call!

您将这 3 个事物的类型放在尖括号中:

You place the types of these 3 things in the angle brackets:

<Params, Progress, Result>

因此,如果您要传入 URLs 并使用 Integers 来更新进度并返回一个表示成功的布尔值,您应该这样写:

So if you are going to pass in URLs and use Integers to update progress and return a Boolean indicating success you would write:

public MyClass extends AsyncTask<URL, Integer, Boolean> {

在这种情况下,例如,如果您正在下载位图,您将在后台处理您对位图所做的事情.如果需要,您也可以只返回位图的 HashMap.还要记住你使用的成员变量是不受限制的,所以不要被参数、进度和结果束缚太多.

In this case, if you are downloading Bitmaps for example, you would be handling what you do with the Bitmaps in the background. You could also just return a HashMap of Bitmaps if you wanted. Also remember the member variables you use are not restricted, so don't feel too tied down by params, progress, and result.

要启动 AsyncTask 实例化它,然后按顺序或并行执行它.在执行中是您传递变量的地方.您可以传入多个.

To launch an AsyncTask instantiate it, and then execute it either sequentially or in parallel. In the execution is where you pass in your variables. You can pass in more than one.

请注意,您不要直接调用doInBackground().这是因为这样做会破坏 AsyncTask 的魔力,即 doInBackground() 在后台线程中完成.直接按原样调用它会使其在 UI 线程中运行.因此,您应该使用一种形式的 execute().execute() 的工作是在后台线程而不是 UI 线程中启动 doInBackground().

Note that you do not call doInBackground() directly. This is because doing so would break the magic of the AsyncTask, which is that doInBackground() is done in a background thread. Calling it directly as is, would make it run in the UI thread. So, instead you should use a form of execute(). The job of execute() is to kick off the doInBackground() in a background thread and not the UI thread.

使用上面的示例.

...
myBgTask = new MyClass();
myBgTask.execute(url1, url2, url3, url4);
...

onPostExecute 将在执行的所有任务完成后触发.

onPostExecute will fire when all the tasks from execute are done.

myBgTask1 = new MyClass().execute(url1, url2);
myBgTask2 = new MyClass().execute(urlThis, urlThat);

注意如何将多个参数传递给 execute(),后者将多个参数传递给 doInBackground().这是通过使用 varargs(你知道像 String.format(...).很多例子只展示了使用 params[0] 提取第一个参数,但是您应该确保您获得所有参数.如果您要传入 URL,这将是(取自 AsynTask 示例,有多种方法可以做到这一点):

Notice how you can pass multiple parameters to execute() which passes the multiple parameter on to doInBackground(). This is through the use of varargs (you know like String.format(...). Many examples only show the extraction of the first params by using params[0], but you should make sure you get all the params. If you are passing in URLs this would be (taken from the AsynTask example, there are multiple ways to do this):

 // This method is not called directly. 
 // It is fired through the use of execute()
 // It returns the third type in the brackets <...>
 // and it is passed the first type in the brackets <...>
 // and it can use the second type in the brackets <...> to track progress
 protected Long doInBackground(URL... urls) 
 {
         int count = urls.length;
         long totalSize = 0;

         // This will download stuff from each URL passed in
         for (int i = 0; i < count; i++) 
         {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
         }

         // This will return once when all the URLs for this AsyncTask instance
         // have been downloaded
         return totalSize;
 }

如果你打算做多个 bg 任务,那么你要考虑上面的 myBgTask1myBgTask2 调用将顺序进行.如果一个调用依赖于另一个调用,这很好,但是如果调用是独立的——例如,您正在下载多个图像,并且您不关心哪个先到达——那么您可以制作 myBgTask1myBgTask2THREAD_POOL_EXECUTOR 并行调用:

If you are going to be doing multiple bg tasks, then you want to consider that the above myBgTask1 and myBgTask2 calls will be made in sequence. This is great if one call depends on the other, but if the calls are independent - for example you are downloading multiple images, and you don't care which ones arrive first - then you can make the myBgTask1 and myBgTask2 calls in parallel with the THREAD_POOL_EXECUTOR:

myBgTask1 = new MyClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url1, url2);
myBgTask2 = new MyClass().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, urlThis, urlThat);

<小时>

注意:

示例

这是一个示例 AsyncTask,它可以在同一个 execute() 命令上采用任意数量的类型.限制是每种类型必须实现相同的接口:

Here is an example AsyncTask that can take as many types as you want on the same execute() command. The restriction is that each type must implement the same interface:

public class BackgroundTask extends AsyncTask<BackgroundTodo, Void, Void>
{
    public static interface BackgroundTodo
    {
        public void run();
    }

    @Override
    protected Void doInBackground(BackgroundTodo... todos)
    {
        for (BackgroundTodo backgroundTodo : todos)
        {
            backgroundTodo.run();

            // This logging is just for fun, to see that they really are different types
            Log.d("BG_TASKS", "Bg task done on type: " + backgroundTodo.getClass().toString());
        }
        return null;
    }
}

现在你可以:

new BackgroundTask().execute(this1, that1, other1); 

这些对象中的每一个都是不同的类型!(实现相同的接口)

Where each of those objects is a different type! (which implements the same interface)

这篇关于如何将变量传入和传出 AsyncTasks?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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