Android runOnUiThread/AsyncTask无法解析CalledFromWrongThreadException

mmr*_*mrn 5 multithreading android handler android-asynctask

我正在为Android应用程序工作并使用AsyncTask类实现ProgressBar.

问题是在某些设备上,它会导致"CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图." 在onPostExecute中.在这些设备上,问题发生在100%.在其他设备上,它工作正常.

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);
    }
Run Code Online (Sandbox Code Playgroud)

我不明白为什么onPostExecute不能在那些特定设备上的UI线程上运行.

接下来,我尝试用runOnUiThread调用它,以确保它在UI线程上运行.

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

即使这样也没有解决问题.同样的异常仍然会发生.

从Log,我确认Thread.currentThread().getId()肯定不同于应用程序的主要活动在处理程序中的线程.

我被卡住了.任何建议将被认真考虑.

注意:我编辑了上面的示例代码(不是真正的代码)来修复错误的方法名称并缺少"返回字符串".我稍后会添加更多信息.

Nat*_*ate 7

我没有看到任何错误MyAsyncTask,但还有其他事情可能会出错.

启动AsyncTask

来自Android Docs

线程规则

此类必须遵循一些线程规则才能正常工作:

  • 必须在UI线程上加载AsyncTask类.这是从JELLY_BEAN开始自动完成的.
  • 必须在UI线程上创建任务实例.
  • 必须在UI线程上调用execute(Params ...).
  • 不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...).
  • 该任务只能执行一次(如果尝试第二次执行,则会抛出异常.)

您没有显示正常实例化的位置,并执行任务,因此请确保您已在UI /主线程上已有的代码中执行此操作.请注意,上面的第一个要点可能解释了为什么这在某些设备上适用于您,而不是在其他设备上.

创建视图层次结构

该消息告诉你

只有创建视图层次结构的原始线程才能触及其视图.

并且你假设这是因为你的异步任务(奇怪地)试图在后台线程上修改UI.但是,您可能会收到此错误,因为异步任务会修改主线程上的UI,但ProgressBar首先未正确创建UI().

请参阅此问题,了解如何在错误的线程(线程以外的任何其他线程)上错误地创建视图,并获得相同的错误.

更多

但是,我想知道您确切记录线程ID的位置,以及您获得的值.如果您查看我的前两个建议,但它们无法解决您的问题,那么我们可能需要更多信息.

您还提到了Handler(?),但没有显示您使用它的方式或位置.通常情况下,使用AsyncTask不需要使用Handler,所以我有点担心你如何使用它.

更新

根据下面评论中的讨论,看起来这里的问题是这个问题中讨论的问题.一些代码,大概在后台线程运行时,首先引起AsyncTask 加载.AsyncTask在主线程上发生所需类加载的原始(pre-Jelly Bean)实现(如上面的线程规则中所述).简单的解决方法是在主线程(例如in Application#onCreate())上添加强制执行早期确定性类加载的代码AsyncTask:

Class.forName("android.os.AsyncTask");
Run Code Online (Sandbox Code Playgroud)