Async Task OnProgressUpdate CalledFromWrongThreadException: только исходный поток, создавший иерархию представлений, может коснуться его представлений

Я использую AsyncTask для загрузки базы данных с progressdialog, который показывает прогресс в пользовательском интерфейсе. Некоторые из моих пользователей получают ошибку:

CalledFromWrongThreadException: только исходный поток, создавший иерархию представлений, может коснуться его представлений.

Насколько я понимаю, это должно произойти только в том случае, если вы пытаетесь обновить Views от потока пользовательского интерфейса. Вот ошибка:

Com … updateops.DbCreate.onProgressUpdate (DbCreate.java:70) at com … updateops.DbCreate.onProgressUpdate (DbCreate.java:1)

И вот мой код:

public class DbCreate extends AsyncTask<String, String, String>{ private static Context mCtx; private static ProgressDialog mDialog; public static AmazonSimpleDBClient mSDbClient; public static AmazonS3Client mS3Client; private static int mAppVersion; private static boolean mCreate; public DbCreate(Context ctx, int versionCode, boolean create) { mCtx = ctx.getApplicationContext(); mAppVersion = versionCode; mDialog = new ProgressDialog(ctx); mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mDialog.setMessage("Checking for server access. Please wait..."); mDialog.setCancelable(false); mDialog.setMax(1); mDialog.show(); mCreate = create; } protected void onProgressUpdate(String... name) { if (name[0].equals("item")) { mDialog.incrementProgressBy(1); } else if (name[0].equals("setMax")) { mDialog.setProgress(0); mDialog.setMax(Integer.parseInt(name[1])); <-- This is line 70 }} @Override protected String doInBackground(String... arg0) { **do stuff** publishProgress("setMax", ""+ 3); } 

Мне кажется, что я точно следую тому, что должен сделать, чтобы избежать этой ошибки. Кто-нибудь знает, почему это происходит?

Изменить: Следует также упомянуть, что этот код работает большую часть времени. Я получаю отчеты о сбоях в консоли разработчика.

В соответствии с onProgressUpdate (Прогресс …) вызывается в потоке пользовательского интерфейса после вызова publishProgress (Прогресс …).

Вы должны проанализировать весь отчет журнала, чтобы проверить, есть ли вероятность, что ваша задача async была создана в другом потоке .

И если вы действительно не можете найти основную причину, вы можете использовать обработчик, созданный в потоке пользовательского интерфейса, для обхода.

Вы правильно выглядите, и в большинстве случаев он должен работать. Я предлагаю вам использовать обработчик. Вы можете написать обработчик в потоке пользовательского интерфейса и вызвать его из onProgressUpdate (). Это полностью обеспечит выполнение работы пользовательского интерфейса в потоке пользовательского интерфейса.

Это точно определит вашу проблему, но я не знаю, почему вы получаете ошибку gettin из первых рук. Я видел этот вопрос раньше и не получил конкретной причины для этого.

У меня была та же проблема, которую вы описываете, и я исправил ее с помощью runOnUiThread() с контекстом, принадлежащим AsyncTask (как и в вашем примере).

Следующее решение должно освободить ваши проблемы;

  @Override protected void onProgressUpdate(final String... messages){ myActivityReference.runOnUiThread(new Runnable() { @Override public void run() { // Your UI changes here. } }); } 

Стоит отметить, что мой AsyncTask изначально вызывался из AlertDialog , и это, по моему мнению, вызывает проблему.

Я нашел ту же проблему на устройствах Android 2.3.x и вот журнал сбоев:

 android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. at android.view.ViewRoot.checkThread(ViewRoot.java:2934) ... at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:130) at android.os.HandlerThread.run(HandlerThread.java:60) 

Журнал показывает, что onProgressUpdate и onPostExecute выполняются на HandlerThread который по существу является рабочим потоком с пользовательским Looper . Вот почему происходит авария.

Поэтому в вашем случае, вероятно, внутренний обработчик AsyncTask связан с не основным петлером, связанным с рабочим потоком, например HandlerThread а onUpdateProgress обрабатывается вместо рабочего потока.

Я обнаружил, что эта ошибка появляется повсеместно на устройствах Android 2.3. Поэтому я проверил исходный код AsyncTask в 2.3 и нашел следующее:

 private static final InternalHandler sHandler = new InternalHandler(); private static class InternalHandler extends Handler { @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"}) @Override public void handleMessage(Message msg) { ... } } 

Вероятность того, что внутренний обработчик может быть привязан к не основному петлеукладчику.

Я также проверил последний исходный код AsyncTask и увидел изменение:

 private static class InternalHandler extends Handler { public InternalHandler() { super(Looper.getMainLooper()); } ... } 

Конструктор InternalHandler исключает вероятность того, что он может быть связан с не основным onUpdateProgress поэтому onUpdateProgress ведет себя нормально на почтовых устройствах Android 2.3.