title: Android Loading ListView from another Thread
body: <p>Please explain me why this code does not work?(I need to call the <strong>lv.setAdapter (adapterA)</strong> in the <strong>onClick()</strong>. It is necessary to change the adapters). It works if you run code on the main thread, but I need to load data in another Thread. I would be grateful for any ideas. Thank you.</p>
  
  <pre><code>package com.example.examplelist;
  
  import java.text.DateFormat;
  import java.util.ArrayList;
  import java.util.Date;
  import java.util.concurrent.TimeUnit;
  
  import android.app.Activity;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.os.Handler;
  import android.util.Log;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.widget.Button;
  import android.widget.ListView;
  
  public class ActivityElemsExample extends Activity implements OnClickListener {
      ArrayList&lt;Elem&gt; myList;
      Button btn;
      ListView lv;
      AdapterA adapterA;
      AdapterB adapterB;
      boolean running = false;
      Thread thread;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.main);
          btn = (Button)findViewById(R.id.button_loading);
          btn.setOnClickListener(this);
          lv = (ListView)findViewById(R.id.lv);
  
          myList = new ArrayList&lt;Elem&gt;();
          adapterA = new AdapterA(this, myList);
          adapterB = new AdapterB(this, myList);
      }
  
      public void onClick(View button){
          if(!running){
              running = true;
              Log.d("MyLogs", "LOADING");
  
              /*
              if(...){
                  lv.setAdapter(adapterA);
              }
              else{
                  lv.setAdapter(adapterB);
              }
              */
  
              lv.setAdapter(adapterA);
  
              thread = new Thread(new Runnable(){
              public void run(){
                  myList.clear();
  
                  for(int i=0; i &lt; 3000; i++){
                      myList.add(new Elem(i, System.currentTimeMillis(), "Elem "+i));
                  }
                  handler.sendEmptyMessage(1);
              }
              });
              thread.start();
          }
      }
  
      public void onDestroy(){
          super.onDestroy();
          if(thread != null){
              while(true){
                  try{
                      thread.join();
                      break;
                  }
                  catch (InterruptedException e){}
              }
          }
      }
  
      public Handler handler = new Handler() {
          public void handleMessage(android.os.Message msg) {
              /*
               if(...){
  
               }
               else{
  
               }
               */
  
              adapterA.notifyDataSetInvalidated();
              adapterA.notifyDataSetChanged();
  
              running = false;
          }
      };
  }
  </code></pre>
  
  <p>Log:</p>
  
  <pre><code>FATAL EXCEPTION: main
  Process: com.example.examplelist, PID:553
  java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its contentges ...
  </code></pre>