2012-06-15 161 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()是否執行。

我認爲它提供了一些幫助。

謝謝。

相關問題