title: Creating additional threads inside an AsyncTask in android and updating the UI using an ExecutorService, am I doing it wrong?
body: <p>I'm working on an Android app and I've got an Activity on which I am displaying two TableLayout's on top of each other. The first TableLayout holds a scoreboard for a race (type 1) and the second the scoreboard for another race (type 2).</p>
  
  <p>I inflate both of these TableLayout's from the same XML layout file. I populate them with data from a doInBackground() (AsyncTask). However, the population part is pretty heavy, so I have put this into a custom synchronized method (inside the AsyncTask class) and pass the inflated TableLayout objects as an argument to this method.</p>
  
  <p>I call said method from the doInBackground() method by using an ExecutorService object. This ExecutorService object is created with Executors.newSingleThreadExecutor(). I put the first method call in one Runnable and the second method call in another Runnable and fire off the ExecutorService.execute() on these runnables.</p>
  
  <p>In the method I am accessing UI elements by calling findViewById() on the passed in TableLayout object parameter and calling methods like TextView.setText() on these views. This works fine most of the time, but I am starting to see a some exceptions like</p>
  
  <pre><code>ERROR/AndroidRuntime(409): FATAL EXCEPTION: pool-9-thread-1
      android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
  </code></pre>
  
  <p>and</p>
  
  <pre><code>ERROR/AndroidRuntime(378): FATAL EXCEPTION: pool-2-thread-1
      java.lang.NullPointerException
  </code></pre>
  
  <p>which lets me to belive that I must be doing this incredibly backwards. I'll include a simplified code snippet below to help describe what I am doing currently:</p>
  
  <pre><code>class AddRacesTask extends AsyncTask&lt;Void, View, Void&gt; {
      synchronized void populateTable(ArrayList&lt;Race&gt; data, TableLayout table) {
         TextView headerText = table.findViewById(R.id...);
         headerText.setText("Header");
  
         for(Race race : data) {
            TableRow row = getLayoutInflater().inflate(R.layout....);
  
            TextView pos = row.findViewById(R.id....);
            pos.setText(race.getPos());
  
            TextView person = row.findViewById(R.id....);
            person.setText(race.getPerson());
  
            // etc.
            // etc..
            // etc...
  
            table.addView(row);
  
         }
  
         publishProgress(table);
  
      }
  
      @Override
      private Void doInBackground(Void... voids) {
         ExecutorService executor = Executors.newSingleThreadExecutor();
  
         executor.execute(new Runnable() {
            @Override
            public void run() {
               TableLayout raceType1Layout = getLayoutInflater().inflate(R.layout...);
               populateTable(data, raceType1Layout);
            }
         });
  
         executor.execute(new Runnable() {
            @Override
            public void run() {
               TableLayout raceType2Layout = getLayoutInflater().inflate(R.layout...);
               populateTable(data, raceType1Layout);
            }
         });
      }
  
      @Override
      protected void onProgressUpdate(View... values) {
         if(values[0] instanceof TableLayout) {
            container.addView(values[0]);
         }
      }
  }
  </code></pre>
  
  <p>I welcome any feedback at all. Also if you need more to go on, I'd be happy to post my actual source code but I figured a simplified and clean version would be easier.</p>