有人可以解释如何在Android上使用ASyncTask吗?

时间:2014-03-16 05:54:43

标签: android asynchronous android-asynctask

我一直在做一堆研究并查看Android中ASyncTask的文档,但我似乎无法理解它。我只是想在一个片段在应用程序中可见时运行一些方法,但为了更容易做到这一点,我想我应该使用ASyncTask。我的示例代码如下:

private class syncExample extends ASyncTask <Void, Void, Void>
{
    @Override
    protected void onPreExecute()
    {

    }
    @Override
    protected void doInBackground(Void... voids)
    {

    }
    @Override
    protected void onProgressUpdate()
    {

    }
    @Override
    protected void onPostExecute()
    {

    }
}

现在我的问题如下:

  1. 在尖括号中,我有Void,Void,Void。这些代表到底是什么以及如何知道放置在哪里是正确的?

  2. 对于类中的每个方法,我将每个方法称为void。它们何时应该与void不同(如boolean,String,long等)?

  3. 对于doInBackground方法,我在括号中有Void ...空格。我究竟应该把它放在那里?它们代表什么?

  4. 感谢您的帮助。关于这个的文档对于像我这样的初学者来说并不是很清楚。

4 个答案:

答案 0 :(得分:11)

AsyncTask使用参数化类型(java泛型),以便您可以指定在定义自己的AsyncTask时使用的类型。也许这种形式更容易解释:

public abstract class AsyncTask<Params, Progress, Result> {
    ...
    protected abstract Result doInBackground(Params... params);

    protected abstract void onProgressUpdate(Progress... progress);

    protected abstract void onPostExecute(Result result);
    ...
}

没有名为Params,Progress或Result的类。这些是泛型类型。它们只是您在定义自己的AsyncTask子类时要使用的类型的占位符。上述内容同样可以写成:

public abstract class AsyncTask<A, B, C> {
    ...
    protected abstract C doInBackground(A... params);

    protected abstract void onProgressUpdate(B... progress);

    protected abstract void onPostExecute(C result);
    ...
}

假设我正在定义一个AsyncTask,它接受一个表示URL的字符串列表,它将ping每个字符串以查看它是否可访问,然后返回可到达的数字。同时,每次测试时,每次测试完成后都会更新ProgressBar。它可能看起来像这样:

public class MyAsyncTask extends AsyncTask<String, Integer, Integer> {

    @Override
    protected Integer doInBackground(String... params) {
        int total = params.length;
        int successfulPings = 0;
        for (int i = 0; i < total; i++) {
            if (isReachable(params[i])) {
                successfulPings++;
            }
            publishProgress(i, total);
        }
        return successfulPings;
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        int testsSoFar = progress[0];
        int totalTests = progress[1];
        progressBar.setMax(totalTests);
        progressBar.setProgress(testSoFar);
    }

    @Override    
    protected void onPostExecute(Integer result) {
        Toast.makeTest(context, "Reached " + result + " sites.", Toast.LENGTH_SHORT).show();
    }
}

我会按如下方式启动:

String[] urls = ...
MyAsyncTask task = new MyAsyncTask();
task.execute(urls);

传递给execute的参数将传递给doInBackground。无论你在doInBackground做什么,你都需要将作为参数传入的内容返回给onPostExecute。在doInBackground中,您可以致电publishProgress,在那里您可以像我一样做(但您不必)。

答案 1 :(得分:0)

我的基本建议是更多地研究AsyncTask,但我也会尝试并回答你的问题:

  

1-在尖括号中,我有Void,Void,Void。这些代表到底是什么,我怎么知道放在哪里是正确的?

它们是重写方法的输入参数类型:doInBackground()onPreExecute(),onProgressUpdate()和.......

  

2-对于类中的每个方法,我将每个方法称为void。什么时候应该与void不同(比如boolean,String,   等等)?

我将给你一个例子:onPostExecute()保证在doInBackground()之后被调用,所以如果onPostExecute(int someCounter)在其输入中有一个整数,那么doInBackground()应该返回一个整数而不是void。所以它将被声明为:

 int doInBackground(){
//bla bla bla
int someIntegerValue;
return someIntegerValue;
}
  

3-对于doInBackground()方法,我在括号中有Void ...空格。我究竟应该把它放在那里?他们是什么   代表什么?

它们是var-args,基本上,它们代表可变数量的参数。 详细了解他们here

我再次建议您深入研究Android中的线程,并了解为什么需要AsyncTask。 祝你好运,

答案 2 :(得分:0)

异步任务使用的三种类型如下:

  1. Params,执行时发送给任务的参数类型。即如果要将一些变量/数组发送到异步任务后台任务。您可以使用该变量来使用该信息。

  2. 进度,后台计算期间发布的进度单元的类型。即显示您的后台进度的进度。 (例如显示下载了多少视频/图像)

    1. 结果,后台计算结果的类型。即你在用于将结果传递给onPostExecute方法的后台进程中计算的结果。
  3. String [] username;

    用户名[0] = “USER1”;  用户名[1] = “用户2”;

    new asynctask()。execute(username);

    private class asynctask extends AsyncTask <USER, Integer, String>
    {
    @Override
    protected void onPreExecute()
    {
       // anything you want to do prior starting the async task.
    }
    @Override
    protected String doInBackground(USER... users)
    {
         int count = users.length;
         for (int i = 0; i < count; i++) 
            retriveinformation(users[i]); 
    return "Hey";
    }
     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }
    
     protected void onPostExecute(String result) {
    
             // the value result is HEY that is returned by doInBackground.
     }
    

    }

    并非所有类型都始终由异步任务使用。要将类型标记为未使用,只需使用类型Void。

    取自https://developer.android.com/reference/android/os/AsyncTask.html

    的信息

答案 3 :(得分:0)

让我试试这个。我正在解析的所有信息都来自Karakuri在对问题的评论中分享的链接。

尖括号的内容按顺序称为“参数”,“进度”和“结果”。参数是将被输入“doInBackground”的参数类型(使用varargs)。它们将通过该方法在数组中接收。您将使用这些参数作为数据在后台线程中进行处理。

“进度”是输入onProgressUpdate的值的类型。覆盖此方法时,您将接收此类型的数据,对其进行格式化,并在进度显示中使用它。从我的阅读中,您可以在doInBackground中发布您的进度,以供onProgressUpdate使用。

“结果”是操作结果的数据类型。这将是doInBackground的返回类型,以及onPostExecute的参数类型。 对于包含“...”(称为varargs)的参数,您可以根据需要输入任意数量的参数。它们必须用逗号分隔,并且必须都是“......”之前指定的类型。这些项目将传递给数组中的函数。所以,回答你的问题:

  1. 当后台任务需要接收要处理的数据时,您将从空格中更改尖括号中的第一个参数。类型将是您要传入的数据类型。当您希望跟踪进度时,您将更改第二个参数。类型将是您希望用于跟踪的任何类型,您将需要在“doInBackground”中自己进行所有跟踪。当后台任务需要返回数据时,您将更改第三个参数。类型将是您希望返回的数据类型。数据将提供给“onPostExecute”。这很重要,因为AsyncTask.execute()没有返回值,因此您必须使用该方法中的任何必要数据将其传递给调用AsyncTask.execute()的类。
  2. onPreExecute似乎总是类型为void。 doInBackground将是结果类型,尖括号中的第3个参数。 onProgressUpdate似乎总是无效。 onPostExecute似乎总是无效。
  3. doInBackground的参数将是一个类型标签,后跟三个点和一个名称。标签的类型必须与尖括号中的第一个参数相同。这个名字就是你想要的。然后将该名称分配给类型标签中指定类型的数组,并传入以供在doInBackground主体中使用。
  4. 一些想法:如果您是初学者,请暂时将“progress”保留为空,并且不要覆盖onProgressUpdate。它在生产代码中非常重要,但对于初学者学习项目来说却是一项额外的艰苦工作。 onPreExecute也可能比你的等级值得更麻烦。只记得它们存在,当你需要它们时,你可能会知道。此外,仅仅因为难以避免多线程主题的良好工作。