Async Task OnProgressUpdate CalledFromWrongThreadException: only the source thread that created the view hierarchy can touch its views

I use AsyncTask to load the database with a progressive dialog that shows the progress in the user interface. Some of my users receive an error message:

CalledFromWrongThreadException: only the source thread that created the view hierarchy can touch its views.

As I understand it, this should only happen if you are trying to update Views from a UI thread. Here is the error:

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

and here is my code:

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); } 

It seems to me that I am exactly following what I should do to avoid this error. Does anyone know why this is happening?

Edit: I should also mention that this code works most of the time. I get crash reports in the developer console.

+4
source share
4 answers

According to onProgressUpdate (Progress ...) is called in the user interface thread after calling publishProgress (Progress ...).

You should analyze the entire log report to check if there is a chance that your async task was created in another thread .

And if you really cannot find the root cause, you can use the handler created in the user interface thread to work around.

+4
source

The code looks good, and in most cases it should work. I suggest you use a handler. You can write a handler in the user interface thread and call it from onProgressUpdate (). This will fully ensure that the user interface runs in the user interface thread.

This will pinpoint your problem for sure, but I don't know why you get gettin error first hand. I have seen this question before and have not received a specific reason for this.

+1
source

I had the same problem that you are describing, and I fixed it by calling runOnUiThread() against a context owned by AsyncTask (as in your example).

The following solution should free your problems;

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

It is worth noting that my AsyncTask was originally called from within the AlertDialog , which in my opinion is causing the problem.

+1
source

I found the same problem on Android 2.3.x devices and here is the crash log:

 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) 

The log shows that onProgressUpdate and onPostExecute run on HandlerThread , which is essentially a workflow with a custom Looper . Therefore, why the failure occurs.

Therefore, in your case, it is likely that the AsyncTask internal handler AsyncTask bound to a non-main looper associated with the workflow, for example HandlerThread and onUpdateProgress instead processed in the onUpdateProgress .

I found that this error appears everywhere on Android 2.3 devices. So I checked the AsyncTask source code in 2.3 and found this:

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

The likelihood that the internal handler may be associated with a non-main looper.

I also checked the latest AsyncTask source code and saw a change:

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

The InternalHandler constructor eliminates the possibility that it may be associated with a non-main looper, so onUpdateProgress behaves normally on Android 2.3 mail devices.

0
source

Source: https://habr.com/ru/post/1500406/


All Articles