调用AsyncTask的onPostExecute:但doInBackground不会

时间:2012-06-15 19:34:34

标签: android android-asynctask

我有一个奇怪的问题,我不确定我做错了什么或什么的。 出于某种原因,我的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确实为null,除非调用doInBackground(),否则它将为null。我知道doInBackground永远不会因为空指针而调用,因为我放在它身上的Log永远不会被调用。那么什么可能导致我的doInBackground()方法不被调用?如果重要,我在onResume方法中执行AsyncTask,并且我不在onCreate或onStart中执行任何其他AsyncTasks。

3 个答案:

答案 0 :(得分: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);
                }
            }
        }

可能导致theEntries为null。另外,我认为你可以做得更好。而不是在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。

答案 1 :(得分:0)

此问题已由其他人发布(有关相关问题,请参见侧栏)。截至目前,这个问题仍然没有解决方案。我自己遇到了这个问题,经过几天的挣扎,我接受了这个错误。 你可以做的是使用Activity.runOnUiThread()。它将解决您遇到的此问题,但不会解决AsyncTasks的问题。这就是我解决这个问题的方法。

答案 2 :(得分: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()是否执行。

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

感谢。