【问题标题】:AsyncTask onPostExecute() is never called + W/art: Suspending all threads took: 1.1ms永远不会调用 AsyncTask onPostExecute() + W/art:暂停所有线程占用时间:1.1 毫秒
【发布时间】:2016-04-09 18:10:07
【问题描述】:

我知道有很多关于此的AsyncTask 问题,但没有一个对我有帮助。

我有一个AsyncTask,它使用Jsoup 处理一些HTML 解析。

我无数次调试了应用程序(真的),在调用doInBackground() 方法后,我得到了我想要发送到onPostExecute() 方法的值,但问题是onPostExecute() 方法从未被调用。

我想这很简单。

只是相关的代码。

MainActivity.java:

private HtmlPage htmlPage = new HtmlPage();

    private static final String ASYNC_TASK_TAG = "AsyncTask";

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Getting the HTML document from a background thread
        new GetHtmlDocument("someUrlString").execute();

        if (this.htmlPage.getHtmlDocument() != null)
        {
            new GetHtmlDocument("someUrlString").cancel(true);
        }

        while (this.htmlPage.getHtmlDocument() == null)
        {
            if (this.htmlPage.getHtmlDocument() != null)
            {
                new GetHtmlDocument("someUrlString").cancel(true);
            }
            else
            {
                new GetHtmlDocument("someUrlString").execute();
            }
        }
    }

AsyncTask 内部类:

private class GetHtmlDocument extends AsyncTask<String,Void,HtmlPage>
    {
        private String url;

        /**
         * Constructor.
         *
         * @param url Url to parse from in the web.
         */
        public GetHtmlDocument(String url)
        {
            this.url = url;
        }

        @Override
        protected void onPreExecute()
        {
            Log.d(MainActivity.ASYNC_TASK_TAG, "onPreExecute() called");
        }

        @Override
        protected HtmlPage doInBackground(String... params)
        {
            //android.os.Debug.waitForDebugger();
            Log.d(MainActivity.ASYNC_TASK_TAG, "doInBackground() called");

            // Get the HTML http://www.lyricsplanet.com/ document
            HtmlPage htmlPage = new HtmlPage(getParsedDocument(this.url));

            return htmlPage;
        }

        @Override
        protected void onPostExecute(HtmlPage htmlPage)
        {
            Log.d(MainActivity.ASYNC_TASK_TAG, "onPostExecute() called");

            if (htmlPage.getHtmlDocument() != null)
            {
                this.cancel(true);
            }

            setHtmlPage(htmlPage);
        }

        /**
         * A task can be cancelled at any time by invoking cancel(boolean).
         * Invoking this method will cause subsequent calls to isCancelled() to return true.
         * After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns.
         * To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
         *
         * @param htmlPage
         *
         */
        @Override
        protected void onCancelled(HtmlPage htmlPage)
        {
            Log.d(MainActivity.ASYNC_TASK_TAG, "onCancelled() called");
        }
    }

onPostExecute()中使用的方法:

public void setHtmlPage(HtmlPage htmlPage)
    {
        this.htmlPage = htmlPage;
    }

HtmlPage.java:

public class HtmlPage
{
    private Document htmlDocument;

    public HtmlPage(Document htmlDocument)
    {
        this.htmlDocument = htmlDocument;
    }
}

doInBackground()中使用的方法:

   public Document getParsedDocument(String url)
    {
        try
        {
            return Jsoup.connect(url).get();
        }
        catch (IOException e) // On error
        {
            e.printStackTrace();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return null; // Failed to connect to the url
    }

我想问题出在主要的Thread 上,它永远没有机会调用onPostExecute() 方法,或者我的AsyncTaskGeneric 参数或我的AsyncTask 类的实现。

任何建议将不胜感激。

编辑:

我忘记了W/art: Suspending all threads took: 1.1ms 警告。我得到它来运行应用程序。但是当我调试应用程序时,我没有得到它,并且我清楚地看到在 doInBackground() 方法中生成的 HtmlPage 对象得到了我想要的值。

【问题讨论】:

  • 不清楚为什么你在 onCreate() 启动后立即取消任务,这可能是问题所在。
  • @Egor 如果我从AsyncTask 得到我想要的,这是一个不为空的HtmlPage 对象,我只需取消AsyncTask 执行。顺便说一句,即使我删除了那条线,它也保持不变。
  • AsyncTask 就是这样 - 异步,执行在不同的线程上运行,所以你不能指望调用 execute() 并在下一行代码中得到结果。
  • @Egor 我知道,但不幸的是删除取消语句不是问题。
  • @Egor Suspending all threads 警告呢?

标签: android multithreading asynchronous android-asynctask jsoup


【解决方案1】:

只需调用new GetHtmlDocument("someUrlString").execute(); 并在 onPostExecute() 中等待结果。无需使用 while 循环(阻塞您的 UI 线程)或调用 cancel()(实际上它默认不做任何事情,请查看底部的链接)。

注意,

AsyncTask 应该只用于需要几秒钟的任务/操作;

AsyncTask 在单个后台线程上串行执行(来自 API 11)。所以长时间运行的工人可以阻止其他人;

其他一些gotchas

【讨论】:

  • 谢谢。我会复习的。
【解决方案2】:

这是因为您的 onCreate() 启动 AsyncTask 然后通过 while 循环进行轮询,等待完成的数据。它正在饿死任何其他线程。您需要异步处理结果。尝试使用Handler 并在完成后让onPostExecute() 发送消息。

【讨论】:

  • Handler 您指的是stackoverflow.com/questions/11713625/… ----- 或在主Thread 上初始化的接口,这是AsyncTask 类属性的一部分?谢谢你的帮助。
  • 可以参考一下吗? stackoverflow.com/questions/36528668/…
  • 您可以使用在您的onCreate 中创建的Handler。或者,如果操作正确,直接在onPostExecute 中执行操作。你需要小心AsyncTask,因为它不知道生命周期,如果允许直接操作 UI 组件,它可能会导致问题。本文将帮助解释:po.st/Cei3m2
猜你喜欢
  • 2011-05-28
  • 2016-07-20
  • 2013-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多