Android的runOnUiThread / AsyncTask的无法解析CalledFromWrongThreadException [英] Android runOnUiThread/AsyncTask cannot resolve CalledFromWrongThreadException

查看:416
本文介绍了Android的runOnUiThread / AsyncTask的无法解析CalledFromWrongThreadException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作了一个Android应用程序,并通过使用AsyncTask的类实施进度。

I'm working for an Android app and implementing a ProgressBar by using AsyncTask class.

问题是,在某些设备上,它会导致CalledFromWrongThreadException:只有原始的创建视图层次可以触摸其观点线程。在onPostExecute。在这些设备中,问题出现100%。在其他设备上,它工作正常。

The problem is that on some devices, it causes "CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views." in onPostExecute. On those devices, the problem occurs 100%. On other devices, it works fine.

public final class MyAsyncTask extends AsyncTask<String, Integer, String>
{
    private ProgressBar progress;
    private ListActivity activity;

    public MyAsyncTask(ListActivity activity, ProgressBar progress)
    {
        this.progress = progress;
        this.activity = activity;
    }

    protected void onPreExecute()
    {
        this.progress.setVisibility(view.VISIBLE);
    }

    protected String doInBackground(String[] arg0)
    {
        // getting xml via httpClient
        return string;
    }

    protected void onPostExecute(String result)
    {
        this.progress.setVisibility(view.GONE);
    }

我不明白为什么onPostExecute不会在UI线程上运行,在这些特定的设备。

I don't understand why onPostExecute does not run on the UI thread, on those certain devices.

接下来,我试着用runOnUiThread称呼它,绝对确保它运行在UI线程上。

Next, I tried to call it with runOnUiThread, to make absolutely sure that it runs on the UI thread.

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        ProgressBar progress = (ProgressBar)findViewById(R.id.some_view_progressbar);
        MyAsyncTask task = new MyAsyncTask(activity, progress);
        task.execute();
    }
} );

即使这并没有解决问题。仍然出现同样的异常。

Even this did not solve the problem. The same exception still occurs.

从日志,我证实了Thread.currentThread()。的getId()是从处理程序内的应用程序的主活动的线程肯定是不同的。

From Log, I confirmed that Thread.currentThread().getId() is certainly different from the app's main activity's thread inside the handler.

我卡住了。任何意见将是AP preciated。

I'm stuck. Any advice will be appreciated.

请注意:我编辑的样本code(不是一个真正的code)项修正错误的方法名失踪返回字符串。
稍后我会添加更多的信息。

NOTE:I edited the sample code (not a real code) above to fix the wrong method name and missing "return string". I will add more information later.

推荐答案

我不明白的任何 MyAsyncTask 本身,但有还是其他的东西,可能会出错。

I don't see anything wrong with MyAsyncTask itself, but there are still other things that can go wrong.

Android电子文档

线程规则

有必须遵循这个类的几个线程规则
  正常工作:

There are a few threading rules that must be followed for this class to work properly:


      
  • 的AsyncTask的类必须在UI线程上加载。这是因为JELLY_BEAN的自动完成。

  •   
  • 任务实例必须在UI线程上创建的。

  •   
  • 执行(参数...)必须在UI线程调用。

  •   
  • 请不要在preExecute(),onPostExecute(结果),doInBackground(参数...),onProgressUpdate(进展...)手动。
  • 打电话
      
  • 任务只能执行一次(如果第二次尝试执行一个异常将被抛出。)

  •   

您不显示在您的正常的实例,以及执行任务,所以请确保您在code这已经是UI /主线程上做到这一点。需要注意的是上述第一点或许可以解释为什么这对你的作品在某些设备上,而不是其他。

You don't show where you normally instantiate, and execute the task, so make sure that you do this in code that's already on the UI/main thread. Note that the first bullet point above might explain why this works for you on some devices, and not on others.

的消息告诉你。

只有创建视图层次可以触摸其观点原来的线程。

Only the original thread that created a view hierarchy can touch its views.

和你假设这是因为你的异步任务是(奇怪)试图修改后台线程的用户界面。然而,这是可能的,因为异步任务修改主线程的用户界面,你得到这个错误,但用户界面(进度)没有正确摆在首位创建。

and you're assuming that this is because your async task is (strangely) trying to modify the UI on a background thread. However, it is possible that you get this error because the async task modifies the UI on the main thread, but the UI (ProgressBar) was not created correctly in the first place.

对于您如何错误地错误的线程上创建视图的例子来看看这个问题(比其他任何的主要的线程),并获得这个同样的错误。

See this question for an example of how you can erroneously create the view on the wrong thread (anything other than the main thread), and get this same error.

我会,但是,想看看究竟的其中,您登录线程ID,和什么样的价值(S)你得到。如果你看看我的前两个建议,他们不解决您的问题,那么我们可能需要更多的信息。

I would, however, like to see exactly where you are logging the thread ID, and what value(s) you're getting. If you check out my first two suggestions, and they don't solve your problem, then we may need more information.

您也提到一个处理程序(?),但不要 T显示如何或在哪里,你使用它。通常情况下,使用的AsyncTask 不再需要使用处理程序,所以我有点担心你会如何使用这一点。

You also mention a Handler (?), but don't show how or where you use that. Normally, using AsyncTask removes the need to use Handler, so I'm a little worried about how you might be using that.

每在下面评论的讨论中,它看起来像这里的问题是在这个问题上讨论的。有些code,可能在后台线程运行时,首先引起的AsyncTask 加载的。发生在主线程中的原始(pre-Jelly Bean)的实施的AsyncTask 所需的类加载(如上面的线程规则自提)。最简单的解决方法是添加在主线程code(如应用#的onCreate())的部队早,确定性的类加载AsyncTask的

Per the discussion in comments below, it looks like the issue here is the one discussed in this question. Some code, probably running on a background thread, is first to cause the AsyncTask class to be loaded. The original (pre-Jelly Bean) implementation of AsyncTask required class loading to occur on the main thread (as mentioned in the Threading Rules above). The simple workaround is to add code on the main thread (e.g. in Application#onCreate()) that forces early, deterministic class loading of AsyncTask:

Class.forName("android.os.AsyncTask");

这篇关于Android的runOnUiThread / AsyncTask的无法解析CalledFromWrongThreadException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆