2011-09-19 13 views
8

Provo a modificare il contenuto dello Spinner attraverso gli AsyncTaks ma non riesco e il Logcat è scritto "09-19 16: 36: 11.189: ERRORE/ERRORE THE (6078): solo il thread originale che ha creato una gerarchia di viste può tocca le sue opinioni. ".AsyncTask "Solo il thread originale che ha creato una gerarchia di viste può toccare le sue viste."

public class GetGroups extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected Void doInBackground(Void... params) { 
     Spinner combo = (Spinner) findViewById(R.id.group_combo); 

     setGroups(combo); 

     return null; 
    } 

    @Override 
    protected void onPostExecute(Void unused) 
    { 
     super.onPostExecute(unused); 


     Spinner combo = (Spinner) findViewById(R.id.severity_combo); 

     combo.setSelection(1); 

     //updateGroups(); 
     //if (!isFinishing()) 
     //{ 
      /*Spinner combo = (Spinner) findViewById(R.id.group_combo); 
      ProgressBar pg = (ProgressBar) findViewById(R.id.loading_group); 

      pg.setVisibility(ProgressBar.GONE); 
      combo.setVisibility(Spinner.VISIBLE); 

      combo.setSelection(0);*/ 
     //} 
    } 
} 
} 

E i setgroups funzione è:

public void setGroups(Spinner combo) { 

    try { 
     DefaultHttpClient httpClient = new DefaultHttpClient(); 

     HttpPost httpPost = new HttpPost(this.object.url); 

     List<NameValuePair> parameters = new ArrayList<NameValuePair>(2); 
     parameters.add(new BasicNameValuePair("user", this.object.user)); 
     parameters.add(new BasicNameValuePair("pass", this.object.password)); 
     parameters.add(new BasicNameValuePair("op", "get")); 
     parameters.add(new BasicNameValuePair("op2", "groups")); 
     parameters.add(new BasicNameValuePair("other_mode", "url_encode_separator_|")); 
     parameters.add(new BasicNameValuePair("return_type", "csv")); 
     parameters.add(new BasicNameValuePair("other", ";")); 

     UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters); 

     httpPost.setEntity(entity); 

     HttpResponse response = httpClient.execute(httpPost); 
     HttpEntity entityResponse = response.getEntity(); 

     String return_api = this.object.convertStreamToString(entityResponse.getContent()); 

     String[] lines = return_api.split("\n"); 

     ArrayList<String> array = new ArrayList<String>(); 

     for (int i= 0; i < lines.length; i++) { 
      String[] groups = lines[i].split(";", 21); 

      this.pandoraGroups.put(new Integer(groups[0]), groups[1]); 

      array.add(groups[1]); 
     } 

     ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<String>(this, 
      android.R.layout.simple_spinner_item, 
      array); 
     combo.setAdapter(spinnerArrayAdapter); 
    } 
    catch (Exception e) { 
     Log.e("ERROR THE ", e.getMessage()); 

     return; 
    } 
} 

Cosa c'è di sbagliato? Grazie.

+0

è GetGroups una classe interna? –

+1

Cosa stai cercando di fare? – Ronnie

+0

possibile duplicato di [Solo il thread originale che ha creato una gerarchia di viste può toccare le sue viste] (http://stackoverflow.com/questions/10497854/only-the-original-thread-that-created-a-view-hierarchy- can-touch-its-views) –

risposta

10

Si sta tentando di accedere ai componenti dell'interfaccia utente (Visualizza) da un thread in background nel caso all'interno del metodo doInBackground(). Tu sei not allowed to do that.

24

Come indicato da Peter, non è possibile accedere alle viste utilizzando doInBackground(). È possibile farlo all'interno di onPostExecute() tuttavia. È qui che dovresti lavorare con i risultati doInBackground() di ritorno per quanto ne so.

Mi sono imbattuto in questo problema e l'ho risolto spostando il codice di modifica della vista su onPostExecute().

Per quelli di voi che stanno iniziando a raccogliere lo sviluppo di Android:
- doInBackground(): qualunque sia interni avvengono in un altro thread (sullo sfondo) diverso dal thread originale/main tuo views/frammento/attività opera su (questo è il punto di AsyncTask ==> non si può toccare il punto di vista
- onPostExecute(): ora sfondo stoffe sono fatto, qui si torna sul thread principale/thread ==> si può toccare il punto di vista ora

3

Se! vuoi mostrare i progressi durante il processo in background, nessuna delle risposte precedenti ti dà un suggerimento: quando si chiama OnPostExecute tutto è finito ed così non è necessario aggiornare lo stato del caricamento.

Quindi, è necessario eseguire l'override onProgressUpdate nel AsyncTask ed essere sicuri che il secondo oggetto non è un vuoto, ma un intero o una stringa che viene letto dal onProgressUpdate.Ad esempio, utilizzando corde:

public class MyAsyncTask extends AsyncTask<Void, String, Void> { 

    @Override 
    protected void onProgressUpdate(String... values) { 
     super.onProgressUpdate(values); 
     if (values != null && values.length > 0) { 
      //Your View attribute object in the activity 
      // already initialized in the onCreate! 
      mStatusMessageView.setText(values[0]); 
     } 
    } 
} 

Rispetto al metodo di fondo si chiama publishProgress(value as String) che chiama automaticamente onProgressUpdate metodo che uso principale thread UI:

@Override 
protected Boolean doInBackground(Void... params) { 
    your code... 
    publishProgress("My % status..."); 
    your code... 
    publishProgress("Done!"); 
} 

Più in generale, quando si dichiara un AsyncTask si deve specificare le <Params, Progress, Result> classi che sono passati ai metodi principali, questi possono essere le proprie classi o solo le classi Java:

  • doInBackground(Params... params)
  • onProgressUpdate(Progress... value)
  • onPostExecute(Result... success)
+0

ho chiamato invalidate onProgressUpdate e funziona senza errori. –

3

un po 'più dettagli

Problema:

  • elementi dell'interfaccia utente possono essere modificati solo thread UI. Un'eccezione è il loro metodo postInvalidate() che può essere eseguito dall'esterno del thread UI
  • l'errore che ricevi è causato da un tentativo di modificare un elemento dell'interfaccia utente (a View) dall'esterno del thread dell'interfaccia utente - doInBackground() eseguito su un thread in background

Soluzione:

  • modificare il punto di vista del metodo di onPostExecute() - è eseguito sul thread UI
  • ottenere un riferimento un Activity e utilizzare il suo metodo runOnUiThread(Runnable)
  • seconda dell'uso modifica uno dei metodi post...() s' il View
Problemi correlati