AsyncTask 的 onPostExecute 被调用:但 doInBackground 没有
Posted
技术标签:
【中文标题】AsyncTask 的 onPostExecute 被调用:但 doInBackground 没有【英文标题】:AsyncTask's onPostExecute gets called: But doInBackground Does Not 【发布时间】:2012-06-18 21:38:36 【问题描述】:我遇到了一个奇怪的问题,我不确定我是不是做错了什么。 出于某种原因,我的 AsyncTask 不会调用 doInBackground,但会调用 onPostExecute()。调用此 AsyncTask 至关重要,因为它初始化了我在应用程序的其余部分中需要的变量。
我的主要活动中有一个嵌套类,它扩展了 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() 的方法。 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 而崩溃。抛出空指针异常是因为 theEntries 确实为空,除非调用 doInBackground(),否则它将为空。而且我知道 doInBackground 永远不会因为空指针而被调用,因为我放在它的主体上的 Log 永远不会被调用。那么是什么导致我的 doInBackground() 方法没有被调用呢?如果重要,我会在 onResume 方法中执行 AsyncTask,并且不会在 onCreate 或 onStart 中执行任何其他 AsyncTask。
【问题讨论】:
首先为什么要使用 AsyncTask你确定 doInBackground 没有被调用吗?还有很多其他方法可能导致 theEntries 为空。例如,这里有一个例外:
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 的条目。我相信代码如下所示:
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。
【讨论】:
绝对确定它不会被调用。我现在发现了最初的异常,并且即将弄清楚。你让我思考,我想知道为什么我之前没有注意到这一点,但结果是一个 DropboxException 被抛出,因此该块没有到达终点。无论如何,我还不会唱胜利,但非常感谢您指出另一个可能的例外。我现在正在取得进展。 是的,你指出异常肯定帮助了我!我想知道为什么我自己写的时候没有注意到它被抓住了。非常感谢您的帮助。问题是我的手机由于某种原因没有连接到互联网,因此 DropboxException 被捕获并且不允许阻止继续进行。【参考方案2】:此问题已由其他人发布(相关问题请参见侧栏)。到目前为止,这个问题仍然没有解决方案。我自己也遇到过这个问题,经过几天的努力,我接受了这个错误。
你可以做的是使用Activity.runOnUiThread()
。它将解决您遇到的这个问题,但不会解决 AsyncTasks
的问题。我就是这样解决这个问题的。
【讨论】:
是的,我看到其他人发布了这个问题,但我没有看到任何人在没有调用 doInBackground 的情况下专门调用了 onPostExecute。我看到有人说它不会运行,而其他人说 onPreExecute 会运行(这是有道理的),但是当没有调用 doInBackground 时调用 onPostExecute 是没有意义的。感谢您的帮助,我会试一试。【参考方案3】:您可以通过这种方式检查是否在 onPostExecute() 中调用了 doInBackground()。
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() 是否执行了。
我认为它提供了一些帮助。
谢谢。
【讨论】:
以上是关于AsyncTask 的 onPostExecute 被调用:但 doInBackground 没有的主要内容,如果未能解决你的问题,请参考以下文章
片段中的 Asynctask 未到达 onPostExecute
无法覆盖 AsyncTask 类中的 onPostExecute() 方法或使其触发
onPostExecute() 无法重新运行从活动调用的 asyncTask
AsyncTask中onPostExecute方法的返回类型可以不为void吗?