3

对于我的应用程序(支持 Android 2.2+),我必须检查很多(大约 700 个)不同网页的 HTML 代码,并从每个网页中检索一个名称。我将所有 URL 存储在一个数组中。

我现在使用单个 Asynctask 并使用如下 URL 遍历数组:

(来自 Asynctask 的 doinbackground 的片段)

publishProgress(urls.size());
int a = 0;
for(String code : urls) {
    if(!running) return null;
    try {
    URL url = new URL(code);
    HttpURLConnection con = (HttpURLConnection) url.openConnection();
    naam_codes.put(readStream(con.getInputStream(), true).get(0), code);
      } catch (Exception e) {
        running = false;
      }
    publishProgress(++a);

和 readstream 是:

BufferedReader reader = null;
      ArrayList<String> html = new ArrayList<String>();
      try {
          reader = new BufferedReader(new InputStreamReader(in, Charset.forName("ISO-8859-1")));
          if (snel){
              //reading, matching and stuff
          }
          else {
              //other reading, matching and stuff
            }
          }       
      } catch (IOException e) {
        //pass
      } finally {
         if (reader != null) {
             try {
                 reader.close();
             } catch (IOException e) {
                 return null;
             }
         }
      }
      return html;

现在我的问题是它必须等待一个下载+匹配完成才能开始一个新的。应该可以加快速度吧?在监视了一下之后,该进程似乎没有完全使用 CPU 或互联网带宽(?)。我是否应该在 UI 线程上迭代并执行多个 Asynctask,而不是在一个 Asynctask 中进行迭代?如果是这样,怎么做?

4

1 回答 1

2

在 API 11 之前,多个 AsyncTask 不会利用多个内核。之后,您可以在每次下载/解析时创建一个 AsyncTask,并使用executeOnExecutor带有参数的函数并行执行它们AsyncTask.THREAD_POOL_EXECUTOR

文档中:

执行顺序

首次引入时,AsyncTask 在单个后台线程上串行执行。从 DONUT 开始,这被更改为允许多个任务并行运行的线程池。从 HONEYCOMB 开始,任务在单个线程上执行,以避免并行执行导致的常见应用程序错误。

如果你真的想要并行执行,你可以使用 THREAD_POOL_EXECUTOR 调用 executeOnExecutor(java.util.concurrent.Executor, Object[])。


如果我是你,我会构建自己的服务器(只是一个 CRON 任务在某处启动一个 PHP 脚本 + 一个 MySQL 数据库 + 一个 PHP 脚本来提供您的数据)并且我不会让应用程序进行处理。

让您的服务器完成 700 次下载,解析它们,将您需要的内容存储在数据库中。然后让您的应用程序访问您的服务器脚本,该脚本将从您的数据库中选择所需的信息。

好处:

  • 您的服务器有更好的带宽
  • 它具有更强的处理能力
  • 您的应用程序可以请求他们需要的任何数据,而不是下载和解析数百个页面。

不方便:

  • 您可能会在使新数据可用时产生一点延迟(取决于您的 CRON 任务的执行周期和更新数据库的执行时间)
于 2012-10-20T22:07:52.410 回答