android - AsyncTask 的 onPostExecute 被称为 : But doInBackground Does Not

标签 android android-asynctask

我遇到了一个奇怪的问题,我不确定是我做错了什么。 出于某种原因,我的 AsyncTask 不会调用 doInBackground,但会调用 onPostExecute()。调用此 AsyncTask 至关重要,因为它初始化了一个变量,我将在整个应用程序的其余部分使用它。

我的主要 Activity 中有一个嵌套类,它扩展了 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 由于空指针而永远不会被调用,因为我放在它的主体上的日志永远不会被调用。那么什么会导致我的 doInBackground() 方法没有被调用呢?如果重要,我会在我的 onResume 方法中执行 AsyncTask,并且我不会在 onCreate 或 onStart 中执行任何其他 AsyncTask。

最佳答案

您确定没有调用 doInBackground 吗?还有很多其他方法可能导致 theEntries 为空。例如,这里有一个异常(exception):

        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 为空。另外,我认为你可以用更好的方法来做到这一点。与其在 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。

关于android - AsyncTask 的 onPostExecute 被称为 : But doInBackground Does Not,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11057080/

相关文章:

java - 如何使用 XmlSerializer 实现这一点?

android - 如何修复 Module 依赖于一个或多个 Android Libraries 但在构建 Cordova App 时是一个 Jar

android - 如何在微调器中为已知的 rowid 选择行?

android - 如何让场景更新处理程序在 Action 启动时中断 (AndEngine)?

Android 从 URL 下载图像并在 Imageview 中显示

android - 我们可以在 Android Wear 2.0 中调用任意号码吗?

android - 等待 TextToSpeech onInit() 初始化

android - 从 firebase 数据库中获取多个值

android - 为什么我的 doInBackground 被调用了这么多次?

java - 异步任务方法 : I get error whether I write "@Override" annotation or not