The ability to update the interface in doInBackground

As far as I know, we cannot modify the UI elements from the doInBackground method of the AsyncTask, but it doesn't throw any exceptions when doing the same and changing the TextView's text.

 public class MainActivity extends Activity {

  TextView tv;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    tv = (TextView)findViewById(R.id.tv);
    Toast.makeText(MainActivity.this, "Main : " + Thread.currentThread().getName(), Toast.LENGTH_SHORT).show();
    new DemoAsync().execute();
  }

  class DemoAsync extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... params) {
        String threadName = "Async : " + Thread.currentThread().getName();
         for(int i=0;i<1000;i++) {
            tv.setText("Changed " + i);
        }
        return threadName;
    }

    @Override
    protected void onPostExecute(String threadName) {
        Toast.makeText(MainActivity.this, threadName, Toast.LENGTH_SHORT).show();
    }
   }
 }

      

I tried to check if makeInBackground is working on the main thread, but that doesn't work either. However, when showing Toast in doInbackground, the application crashes as it should. Modifying the TextView should have disabled the app as well. Can someone explain this behavior?

PS - Regarding a possible duplicate, I am running the code on pre lollipop, so the question as well as the selected answer does not apply to this. Also the answer suggests that changing the TextView will crash on subsequent calls (18 to be exact in the case of the selected answer). I updated the code to change the TextView in a loop of 1000 iterations and it still works fine.

+3


source to share


3 answers


You shouldn't be accessing the user interface from doInBackground

, as stated in Android's Processes and Threads documentation :



Don't go to Android UI toolkit from outside the UI.

0


source


This is just a misunderstanding in timing: at first glance it seems that tv.setText("Changed " + i);

in doInBackground () changes the view in the UI,

but



in fact, when the last setText is executed, the UI is not yet ready and activity bound, so the last setText in the loop changes a view that is not yet in the UI.

If we delay the cycle, for example. for 10,000 iterations, the UI will start and we will always get the exception "Only the original thread that created the hierarchy view can touch its view."

0


source


check out here AsyncTask

AsyncTask allows you to use the UI thread correctly and easily. This class allows background operations and results to be published on the UI thread without having to manipulate threads and / or handlers.

Edit: In OOP, you can access a global variable from an inner class. so from this point of view, in this example, the class extending AsyncTask is an inner class, you can access the TextView tv; since execute is called on the main UI thread, thus you can modify, but if it was not an inner class, you cannot access the variable defined according to abstraction, because doInBackground is running on a different thread (and not in the UI ). In short, you cannot change the UI element in doInBackground (), but the inner class can access the globally declared widget object to change the values ​​in the container, as done in this question.

-2


source







All Articles