gpt4 book ai didi

Android runOnUiThread/AsyncTask 无法解析 CalledFromWrongThreadException

转载 作者:塔克拉玛干 更新时间:2023-11-02 22:21:37 24 4
gpt4 key购买 nike

我正在开发一个 Android 应用程序并使用 AsyncTask 类实现 ProgressBar。

问题是在某些设备上,它会导致“CalledFromWrongThreadException:只有创建 View 层次结构的原始线程才能触及它的 View 。”在 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);
}

我不明白为什么 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();
}
} );

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

从日志中,我确认 Thread.currentThread().getId() 肯定不同于应用程序在处理程序中的主 Activity 线程。

我卡住了。任何建议将不胜感激。

注意:我编辑了上面的示例代码(不是真实代码)以修复错误的方法名称和缺少“返回字符串”。我稍后会添加更多信息。

最佳答案

我没有看到 MyAsyncTask 本身有任何错误,但仍有其他可能出错的地方。

启动异步任务

来自Android Docs

Threading rules

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

  • The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.
  • The task instance must be created on the UI thread.
  • execute(Params...) must be invoked on the UI thread.
  • Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
  • The task can be executed only once (an exception will be thrown if a second execution is attempted.)

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

创建 View 层次结构

信息告诉你

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

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

See this question有关如何在错误线程( 线程以外的任何线程)上错误地创建 View 并得到相同错误的示例。

更多

但是,我希望确切地看到您在何处记录线程 ID,以及您获得了什么值。如果您查看我的前两个建议,但它们没有解决您的问题,那么我们可能需要更多信息。

你还提到了一个Handler (?),但不要显示您如何或在何处使用它。通常,使用 AsyncTask 就不需要使用 Handler,所以我有点担心您可能会如何使用它。

更新

根据下面评论中的讨论,这里的问题似乎是 the one discussed in this question .某些代码(可能在后台线程上运行)首先导致 AsyncTask class加载AsyncTask 的原始(Jelly Bean 之前)实现要求类加载发生在主线程上(如上面的线程规则中所述)。简单的解决方法是在主线程上添加代码(例如,在 Application#onCreate() 中)强制 AsyncTask 的早期确定性类加载:

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

关于Android runOnUiThread/AsyncTask 无法解析 CalledFromWrongThreadException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18478347/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com