android的asynctask潜在的错误

时间:2010-12-13 11:53:10

标签: android android-asynctask

我正在为Android开发一个简单的应用程序,并且刚刚尝试切换到使用asynctask来进行应用程序所需的FTP调用和XML解析(这是一个天气应用程序FYI)。

不幸的是,我开始注意到我的应用中出现了非常奇怪的行为。我调试了,并且惊恐地发现doInBackground()方法中的代码执行不正常!

为简洁起见,下面的代码已经过简化(catch语句汇总了),但没有任何必需品发生变化。在onResume()中调用asynctask,然后调用ftp服务器,下载文件,然后解析它。正在发生的事情(我可以​​通过下面的调试语句清楚地看到),是在文件下载完成之前进行的解析调用。因此,就调试语句而言,顺序通常是:

  1. 获取文件之前
  2. 解析文件之前
  3. 解析文件错误后(因为文件尚未下载!)
  4. 获取文件后
  5. 我非常乐意提供更多代码(如果需要,还可以提供所有代码!),并回答任何人可能提出的任何问题。

        @Override
        public void onResume()
        {
           if(!inOnResume)
           {
              inOnResume = true;
              super.onResume();
              File file = new File(getFilesDir(), selectedCity);
              new GetBOMWeatherData().execute(file);
           }
        }
    
        private class GetBOMWeatherData extends AsyncTask<File, Void, Void>
        {
            boolean fileDownloaded = false;
    
            @Override
            protected void onPreExecute()
            {
                showDialog(PROGRESS_KEY);
                super.onPreExecute();
            }
    
            @Override
            protected Void doInBackground(File... params)
            {
                FileOutputStream fos = null;
    
                try
                {
                    fos = new FileOutputStream(params[0]);
                }
                catch (FileNotFoundException e)
                {
                    Log.e("ApiException", "There was an error opening the file output stream.", e);
                    cancel(false);
                }
    
                try
                {
                    Log.d("Before get file", "Before get file");
                    DataRetriever.getPageContent(selectedCity, fos);
                    Log.d("After get file", "After get file");
                    fileDownloaded = true;
                }
                catch (ApiException e)
                {
                    Log.d("After get file with error", "After get file with error");
                    Log.e("ApiException", "There was an error opening the file output stream.", e);
                    cancel(false);
                }
                finally
                {
                    Log.d("After get file finally", "After get file finally");
                }
    
                try
                {
                    Log.d("Before parse file", "Before parse file");
                    forecasts = parseXML(selectedCity);
                    Log.d("After parse file", "After parse file");
                    lastDownloaded.put(selectedCity, new Date());
                }
                catch (FactoryConfigurationError e)
                {
                    Log.d("After parse file with error", "After parse file with error");
                    Log.e("XMLParsingException", "There was an error in the factory configuration.", e);
                    cancel(false);
                }
                finally
                {
                    Log.d("After parse file finally", "After parse file finally");
                }
                return null;
            }
    
            @Override
            protected void onPostExecute(Void file)
            {
                inOnResume = false;
                super.onPostExecute(file);
                dismissDialog(PROGRESS_KEY);
                updateView();
            }
    
            @Override
            protected void onCancelled()
            {
                super.onCancelled();
                showDialog(FAILURE_KEY);
            }
        }
    

    编辑:我发现它无序执行的原因是奇怪的错误开始发生。如果我在主UI线程中运行它可以正常工作,但是只要我把它全部放在asynctask中我就会得到XML解析错误。问题似乎是当我的应用尝试解析文件时,文件未完全下载。

2 个答案:

答案 0 :(得分:1)

你最终可能会运行多个线程。您将看到前一个解析日志完成,然后新的解析日志正在进入下载。由于您可能一次只需要一个,因此您需要使用某种锁定来防止两个同时运行。

答案 1 :(得分:0)

DataRetriever.getPageContent(selectedCity, fos);

这是在另一个线程中执行的,它没有阻塞。所以它在这里崩溃并且不在主线程中完全正常。不要使用它。

SAXParser parseur = SAXParserFactory.newInstance().newSAXParser();

parseur.parse(uri, DefaultHandler);
            // On récupère directement la liste des feeds
           ArrayList<Object> entries = ((DefaultHandler) handler).getData();

当然,这只是在您不将XML文件保存到内存中时。然后你只需要在实现DefaultHandler的类中进行解析。

有关详细信息,请参阅doc。

此致