2010-05-29 4 views
1

Désolé, ma dernière question n'a pas été correctement formulée. Donc, je supprime le contenu et reformule ma question.Android Impossible d'exécuter le thread utilisateur setListAdapter()

J'ai aimé @ChrisBunney répondre à ma question avec un exemple pour traiter l'image dans un autre fil.

est ici le bon code ci-dessous

public class TestActivity extends ListActivity { 

    int count =0; 

    List<String> listString = null; 

    String[] mString = null; 

     private RefreshHandler mRedrawHandler = new RefreshHandler(); 

     class RefreshHandler extends Handler { 

      @Override 

      public void handleMessage(Message msg) { 

       TestActivity.this.updateUI(); 

      } 



      public void sleep(long delayMillis) { 

       this.removeMessages(0); 

       sendMessageDelayed(obtainMessage(0), delayMillis); 

      } 

      }; 



      private void updateUI(){ 



       mRedrawHandler.sleep(1000); 

       listString.add("Test "+count++); 

       String[] mString = new String[listString.size()]; 

       int i = 0; 

       for(String string : listString){ 
        mString[i++]= string; 
       } 

       if(null != mString && mString.length>0) 
       setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,mString)); 


      } 



      @Override 

      public void onCreate(Bundle icicle) { 

      super.onCreate(icicle); 

      setContentView(R.layout.main); 

      listString = new LinkedList<String>(); 


      updateUI(); 


      } 



} 

Ce que je compte faire est la mise à jour de l'interface utilisateur d'appel d'un autre fil.

Ce sera la modification de mon fichier de code ci-dessus.

private class HelperClass implements Runnable{ 

      public void run() { 

       performSomeCalculation(); 

      } 

      /* 
      * This code will populate the list as it is executed. 
      * As and when there is a new element in the list the UI is updated. 
      */ 

      public void performSomeCalculation(){ 

       //update list String 
       updateUI(); 
      } 

/* 




/* 
      * 
      * The new update onCreate method calling another thread that populates the UI thread 
      * 
      */ 

      @Override 

      public void onCreate(Bundle icicle) { 

      super.onCreate(icicle); 

      setContentView(R.layout.main); 

      listString = new LinkedList<String>(); 


      //updateUI(); 

      Thread thread = new Thread(new HelperClass()); 
      thread.start(); 


      } 

Vous pouvez voir dans le code ci-dessus, j'ai créé un helperClass pour effectuer des calculs, comme et quand il est ouput du calcul du fil, il doit mettre à jour le thread d'interface utilisateur.

Je travaille dessus pour le faire fonctionner, si quelqu'un découvre plz mettre à jour mon post.

Merci d'avance.

+0

Il y a beaucoup d'erreurs dans votre code ... par ex. @override au lieu de @overriding. Votre méthode onCreate() n'est pas publique et n'a pas de valeur de retour. Vous appelez hread.start() au lieu de thread.start() ..... comment l'exécutez-vous ???? – RoflcoptrException

+0

Dans ma réponse, j'explique comment utiliser un gestionnaire pour mettre à jour l'interface utilisateur à partir d'un thread différent, mais je ne suis pas sûr de ce que vous essayez d'obtenir avec ce code, donc je ne sais pas si cela résout votre problème. Pouvez-vous expliquer ce que vous essayez d'accomplir? – chrisbunney

+0

Si votre vue de liste a un contenu statique, vous pouvez également définir l'adaptateur de liste dans le remplacement onCreate, sinon, la réponse de Chris se chargera de l'exception. –

Répondre

0

Enfin, avec l'aide de Chris de le code a obtenu une solution à ma propre question.

Plz se référer au code de Chris pour la description de la méthode.

Plz me corriger pour toute perte de convention.

Le contenu du fichier de mise en page est le suivant.

<ListView 
    android:id="@+id/list"   
    android:layout_span="1" 
    android:layout_width="324px" 
    android:layout_height="348px"/> 

Le contenu du fichier java est la suivante.

import java.util.LinkedList; 
import android.app.Activity; 
import android.os.Bundle; 
import android.os.Handler; 
import android.widget.ArrayAdapter; 
import android.widget.ListView; 


public class TestApp extends Activity { 


    private final Handler handler = new Handler(); 

    private final UILoadingHelperClass uiLoadingThread = new UILoadingHelperClass(); 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 

     super.onCreate(savedInstanceState); 

     setContentView(R.layout.main); 

     uiLoadingThread.setListView(R.id.list); 

     new DataLoadingThread(handler, uiLoadingThread);   


    } 


    private class DataLoadingThread extends Thread { 

     int count = 0; 

     LinkedList<String> linkedList = null; 

     private final Handler handler; 

     private final UILoadingHelperClass uiLoadingThread; 


     public DataLoadingThread(Handler handler, UILoadingHelperClass uiLoadingThread) { 
      this.handler = handler; 
      this.uiLoadingThread = uiLoadingThread; 
      this.start(); 
     } 

     @Override 
     public void run() { 

      while(true){ 
       try { 

        Thread.sleep(1000); 

       } catch (InterruptedException e) { 

        e.printStackTrace(); 

       } 

       if(null == linkedList) 
        linkedList = new LinkedList<String>(); 

       linkedList.add("Test "+count++); 

       int i=0; 

       String[] strings = new String[linkedList.size()]; 

       for(String string : linkedList) 
        strings[i++]=string; 

       uiLoadingThread.setSttrings(strings); 

       handler.post(uiLoadingThread); 
      } 

     } 
    } 


    private class UILoadingHelperClass implements Runnable { 

     private ListView listView = null; 

     private String[] strings = null; 

     public void setSttrings(String[] strings){ 
      this.strings = strings; 
     } 

     public void setListView(int id){ 
      listView = (ListView)findViewById(id); 
     } 

     public void run() { 
      if(null != strings && strings.length>0) 
       listView.setAdapter(new ArrayAdapter<String>(TestApp.this,android.R.layout.simple_list_item_1,strings));   

     }  
    } 
} 
0

Si vous souhaitez effectuer des opérations de blocage de threads qui mettent à jour l'interface utilisateur (comme le téléchargement d'une image à partir d'Internet), vous devez utiliser la classe Handler pour créer un rappel.

http://developer.android.com/reference/android/os/Handler.html

La classe Handler se lie au thread d'interface utilisateur et vous permettra d'afficher des objets implémentant l'interface Runnable à une file d'attente d'exécution dans le bon fil.

Cependant, je ne suis pas sûr qu'il soit possible d'atteindre ce que vous semblez vouloir, à partir du code donné. Quelques informations supplémentaires sur les circonstances et le comportement souhaité seraient utiles.

Une implémentation typique utilisant un Handler de mettre à jour l'interface utilisateur, basée sur le code de mon application qui télécharge une carte statique et met à jour l'interface utilisateur, peut ressembler à ceci:

public class HandlerExample extends Activity { 


/** 
* Handler to allow other threads to send executable messages (in the form 
* of Runnable objects) to the main UI thread. This is used to download the 
* static image in a separate thread to stop the UI from blocking 
*/ 
private final Handler handler = new Handler(); 
/** 
* Runnable implementation that, in conjunction with handler, displays a 
* given static map in the ImageView 
*/ 
private final UpdateStaticMap updateStaticMap = new UpdateStaticMap(); 


@Override 
protected void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 

     //... other initialisation 

    // This object implements Runnable and is used to post our update to the Handler 
    updateStaticMap.setImageView((ImageView)findViewById(R.id.venuedetail_mapimage)); 
    // Then we pass the Runnable object, the Handler, and all the data we 
    // need to get the 
    // map into a Thread subclass to avoid blocking the UI thread 
      // Note, the thread is started in the constructor so we don't worry about it here 
    new MapGetter(handler, updateStaticMap); 


} 

/** 
* This private class extends Thread to handle the downloading of the static 
* map separately from the main UI thread to avoid 
* blocking it. It uses the Handler to trigger the UI thread to update the 
* ImageView when it's finished by passing updateStaticMap as a message 
* (it's a Runnable, thus will be executed by the handler in the UI thread). 
* This is necessary as only the thread that created the View components can 
* edit them. 
* 
* @author Chris Bunney 
* 
*/ 
private class MapGetter extends Thread { 

    /** 
    * The Handler associated with the UI thread. Used to pass the map back 
    * to the UI thread 
    */ 
    private final Handler handler; 
    /** 
    * The Runnable implementation used to wrap the bitmap when passing it 
    * back to the UI thread via handler 
    */ 
    private final UpdateStaticMap updateStaticMap; 

    /** 
    * 
    * 
    * @param handler 
    *   Handler for the UI thread so the MapGetter can update the 
    *   ImageView with the map 
    * @param updateStaticMap 
    *   Runnable object that is used to send the map back to and 
    *   update the UI 
    **/ 
    public MapGetter(Handler handler, UpdateStaticMap updateStaticMap) { 
     this.handler = handler; 
     this.updateStaticMap = updateStaticMap; 
     this.start(); 
    } 

    /** 
    * Obtains the Static Map and passes it back to the main 
    * UI thread to be displayed 
    */ 
    @Override 
    public void run() { 
        //Note, the getImage() method is just a stand in for whatever code you need to get the image 
     updateStaticMap.setBitmap(getImage())); 
        //Now our Runnable object has all the data it needs, we post it back to the Handler 
     handler.post(updateStaticMap); 

    } 
} 

/** 
* This class implements the Runnable interface. It acts a message to be 
* delivered to the UI thread. This class updates a given ImageView with a 
* given Bitmap. The ImageView and Bitmap form the payload of the message. 
* This class is necessary because only the thread that created a View can 
* alter it, so the object is passed to the correct thread and executed by 
* it. 
* 
* @author Chris Bunney 
* 
*/ 
private class UpdateStaticMap implements Runnable { 

    /** 
    * The ImageView to target when setting the bitmap 
    */ 
    private ImageView mapImage; 
    /** 
    * The Bitmap to update the ImageView with 
    */ 
    private Bitmap bm; 

    /** 
    * Inserts the Bitmap, bm, into the ImageView, mapImage 
    * 
    */ 
    @Override 
    public void run() { 
     mapImage.setImageBitmap(bm); 
     Log.d(TAG, "run: Static Map Updated"); 
    } 

    /** 
    * Accessor method to insert the bitmap payload into the message 
    * 
    * @param bm 
    *   Static map to be displayed in the UI 
    */ 
    public void setBitmap(Bitmap bm) { 
     this.bm = bm; 
     Log.d(TAG, "setBitmap: Bitmap updated"); 
    } 

    /** 
    * Accessor method to associate the object with a particular ImageView 
    * 
    * @param mapImage 
    *   ImageView that the map should be displayed in 
    */ 
    public void setImageView(ImageView mapImage) { 
     this.mapImage = mapImage; 
     Log.d(TAG, "setImageView: ImageView updated"); 
    } 
} 
} 
+0

Votre implémentation de thread est redondante, car votre runnable est une classe interne et le gestionnaire est un objet membre. –

+0

Pourriez-vous développer cela un peu? Je ne comprends pas très bien ce que tu veux dire. Si vous voulez dire que l'implémentation de thread n'est pas requise, je ne suis pas d'accord. Le but de l'implémentation de thread est d'obtenir les informations requises pour mettre à jour l'interface utilisateur sans provoquer le blocage de l'interface utilisateur lors des opérations de type E/S. Le but de la runnable est d'agir comme un message à passer d'un thread (où il est rempli de données) dans un autre thread (où ces données sont utilisées). Le gestionnaire est le destinataire de ce message. – chrisbunney

+0

@chrisbunney Merci pour la réponse, je l'utilise pour reconstruire mon code. J'ai mis à jour ma question, il devrait être plus clair maintenant en expliquant ce que je cherche. – Ameya

Questions connexes