2012-06-15 126 views
2

我有一个奇怪的问题,我不知道如果我做错了什么或什么的。 出于某种原因,我的AsyncTask不会调用doInBackground,但会调用onPostExecute()。这个AsyncTask被调用是很重要的,因为它初始化了我在整个应用程序的其余部分需要的变量。AsyncTask的onPostExecute被调用:但doInBackground不是

我在扩展AsyncTask的主要活动中有一个嵌套类。这个类需要从用户的Dropbox帐户下载的文件名护理:

protected class FilesLister extends AsyncTask<String, Integer, Long> 
{ 
    @Override 
    protected Long doInBackground(String... params) 
    { 
     Log.i("Entries", "We believe Entries has some values now."); 
     ArrayList<Entry> theFiles = new ArrayList<Entry>(); 
     try 
     { 
      Entry entries = mDBApi.metadata("/", 20000, null, true, null); 
      for (Entry e : entries.contents) 
      { 
       Log.i("Hm", e.fileName()); 
       if (!e.isDeleted) 
       { 
        if(!e.isDir) 
        { 
         theFiles.add(e); 
        } 
       } 
      } 
      theEntries = theFiles.toArray(new Entry[theFiles.size()]); 
     } catch (DropboxException e1) 
     { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
     return null; 
    } 

    protected void onPostExecute(Long result) 
    { 
     super.onPostExecute(result); 
     Log.i("Now", "Calling refresh."); 
     refresh(); 
    } 
} 

就像你所看到的,onPostExecute调用一个方法被称为刷新()。 refresh()实现如下:

public void refresh() 
{ 
    //Sort all this files by last modified date. 
    Arrays.sort(theEntries, new Comparator<Entry>() 
    { 
     @Override 
     public int compare(Entry firstFile, Entry secondFile) 
     { 
      //"EEE, dd MMM yyyy kk:mm:ss ZZZZZ" 
      SimpleDateFormat formater = new SimpleDateFormat("EEE, dd MMM yyyy kk:mm:ss ZZZZZ"); 
      try 
      { 
       Date date1 = (Date)formater.parse(firstFile.modified); 
       Date date2 = (Date)formater.parse(secondFile.modified); 
       return date1.compareTo(date2); 
      } catch (ParseException e1) 
      { 
       e1.printStackTrace(); 
      } 
      return 0; 
     } 
    }); 
    //Now we create a String[] array to hold the names of all the fetched files... 
    ArrayList<String>txtFilesNames = new ArrayList<String>(); 
    for(int i = theEntries.length - 1; i >= 0; i--) 
    { 
     //Loops goes from top to bottom so the latest file appears at the top of the ListView. 
     txtFilesNames.add(theEntries[i].fileName()); 
    } 
    actualFileNames = txtFilesNames.toArray(new String[txtFilesNames.size()]); 
    ArrayAdapter<String> ad = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, actualFileNames); 
    lv.setAdapter(ad); 
} 

我知道refresh()被调用的原因有两个:LogCat日志“调用刷新”。然后由于NullPointerException导致应用程序崩溃。空指针异常被抛出,因为Entries确实为null,除非调用doInBackground(),否则它将为空。我知道doInBackground从来没有被调用,因为空指针,因为我放在它身上的日志永远不会被调用。那么,什么可能导致我的doInBackground()方法不被调用?如果它很重要,我在我的onResume方法中执行AsyncTask,并且我不会在onCreate或onStart中执行任何其他AsyncTasks。

+0

第一件事,第一,为什么你正在使用的AsyncTask <字符串,整数,长>如果你的doinbackground不打算返回任何值何不的AsyncTask <字符串,整数,太虚> ??? – Akram

+0

在doInBackground中设置一个断点,并使用调试器遍历代码。 – Zambotron

回答

1

你确定doInBackground没有被调用吗?还有很多其他方法可能导致条目为空。例如,这里有一个例外:

 Entry entries = mDBApi.metadata("/", 20000, null, true, null); 
     for (Entry e : entries.contents) 
     { 
      Log.i("Hm", e.fileName()); 
      if (!e.isDeleted) 
      { 
       if(!e.isDir) 
       { 
        theFiles.add(e); 
       } 
      } 
     } 

可能导致该条目为空。另外,我认为你可以以更好的方式做到这一点。而不是设置内doInBackground(这是比你的对象被创建在不同的线程),则应该有一个函数返回的条目theEntries的,将通过他们onPostExecute.I相信代码是这样的:

protected class FilesLister extends AsyncTask<String, Integer, Entry[]> 
{ 
    @Override 
    protected Entry[] doInBackground(String... params) 
    { 
     Log.i("Entries", "We believe Entries has some values now."); 
     Entry[] entriesReturn = null; 
     ArrayList<Entry> theFiles = new ArrayList<Entry>(); 
     try 
     { 
      Entry entries = mDBApi.metadata("/", 20000, null, true, null); 
      for (Entry e : entries.contents) 
      { 
       Log.i("Hm", e.fileName()); 
       if (!e.isDeleted) 
       { 
        if(!e.isDir) 
        { 
         theFiles.add(e); 
        } 
       } 
      } 
      entriesReturn = theFiles.toArray(new Entry[theFiles.size()]); 
     } catch (DropboxException e1) 
     { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
     return entriesReturn; 
    } 

    protected void onPostExecute(Entry[] result) 
    { 
     super.onPostExecute(result); 
     Log.i("Now", "Calling refresh."); 
     refresh(result); 
    } 
} 

然后在你的刷新方法中进行赋值。你也应该在刷新方法中检查null。

+0

绝对确定它没有被调用。我现在发现了最初的例外,并且正在仔细研究。你让我想,我想知道为什么我没有注意到这一点,但事实证明DropboxException正在抛出,因此该块没有达到其结束。无论如何,我还不会歌唱胜利,但非常感谢您指出另一个可能的例外。我现在正在取得进展。 –

+0

是的,你指出异常肯定帮助我!我想知道为什么我没有注意到当我自己写这篇文章时它被抓到了。谢谢你的帮助。问题在于我的手机由于某种原因没有连接到互联网,因此DropboxException被捕获并且不允许该程序块继续。 –

0

此问题已由其他人发布(请参阅边栏相关问题)。截至目前,这个问题仍然没有解决办法。我自己遇到了这个问题,经过几天的努力,我接受了这个错误。 你可以做的是使用Activity.runOnUiThread()。它会解决你遇到的这个问题,但不是AsyncTasks的问题。这是我如何解决这个问题。

+0

是的,我看到其他人发布了这个问题,但我没有看到任何人没有调用doInBackground专门有onPostExecute调用。我看到有人说它不会运行,而其他的onPreExecute会运行(这是有道理的),但是当doInBackground没有被调用时调用onPostExecute是没有意义的。我感谢你的帮助,我会试一试。 –

0

您可以通过这种方式检查doInBackground()是否调用onPostExecute()。

protected Long doInBackground(String... params) 
    { 
    /////your code... 
     return 200; 
    } 
    protected void onPostExecute(Long result) 
    { 
     if(result==200) 
{ 
     super.onPostExecute(result); 
     Log.i("Now", "Calling refresh."); 
     refresh(); 
} 
    } 

我不知道您的条目给空值与否。通过这种方式,你可以知道doInBackground()是否执行。

我认为它提供了一些帮助。

谢谢。

相关问题