2011-11-18 14 views
6

Sto sviluppando un'applicazione Android e ho un pulsante che avvia/interrompe determinati processi di simulazione. Mentre questo processo è in esecuzione, ho bisogno di generare alcuni dati da esso in tempo reale. Ma quando creo un nuovo thread per la simulazione, non posso accedere alle viste (lascia che sia TextView) da questo thread, perché è possibile accedervi solo dal thread in cui sono stati creati. D'altra parte, il nuovo thread è necessario perché altrimenti l'utente non sarebbe in grado di fare nulla mentre la simulazione è in esecuzione (ad esempio, premere altri pulsanti). Creare un nuovo servizio richiede anche la creazione di un nuovo thread in questo caso. Come dovrei risolvere questo problema?Accesso alle viste da altro thread (Android)

+0

Avete verificato il [ 'AsyncTask'] (http: // sviluppatore .android.com/reference/android/os/AsyncTask.html) classe? È una classe di utilità che ti aiuta a creare facilmente thread diversi e ad aggiornare di conseguenza gli elementi dell'interfaccia utente. In questo caso potresti usare i metodi 'publishProgress()' e 'onProgressUpdate()'. –

risposta

5

È possibile gestire in molti modi,

  1. tenta di utilizzare AsyncTask in questo, il vostro lavoro sfondo fatto in doInBackGround() metodo e l'interfaccia utente non bloccherà e si può anche accedere alle visualizzazioni di Attività da cui si chiama AsyncTask dal relativo contesto tramite publishProgress() e onProgressUpdate().

  2. Se si utilizza un semplice filo quindi utilizzando Handler o messaggio o runOnUiThread è possibile aggiornare la vista del thread principale.

ma, in your way I think AsyncTask is best for you.

2

È possibile risolvere il problema con android.os.Handler. L'istanza di Handler è legata al thread che la crea, puoi postare Runnables su di essa e li eseguirà nel thread a cui è associata. Ad esempio:

import android.os.Handler; 
import android.widget.TextView; 

public class MyActivity extends Activity { 
    private Handler uiHandler; 
    private TextView simulationStatus; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    ... 
    uiHandler = new Handler(); 
    ... 
    simulationStatus = (TextView) findViewById(R.id.simulationStatus); 
    ... 
    } 

    // This method is to be executed on the simulation thread. 
    public void simulate() { 
    ... 
    final String simulationStatusText = ...; 
    ... 
    uiHandler.post(new Runnable() { 
     @Override 
     public void run() { 
     // This is run on the UI thread. 
     simulationStatus.setText(simulationStatusText); 
     ... 
     } 
    }); 
    } 

    ... 
} 

È inoltre possibile utilizzare AsyncTask. Vedi il link per esempio.

1

Passare l'attività al thread e utilizzarlo dall'interno per accedere alle visualizzazioni.

// from your activity: 
myExternalThread = new MyCustomCode(this); // <-- activity passed 

// your "simulation process" constructor: 
public MyCustomCode(Activity parent) { 
    this.parent = parent; 
} 

// and when you want to access views: 
parent.runOnUiThread(new Runnable() { 
    @Override 
    public void run() { 
     parent.findViewById(R.id.text_view); 
     ... do something to your UI ... 
    } 
}); 

Il mio modo preferito di creazione di queste attività esterne è quello di utilizzare AsyncTask (allora non dovete preoccuparvi di runOnUiThread, tra gli altri benefici). Non so se si applica al tuo caso, ma dovresti verificarlo.

+0

Perché il -1?Alcuna spiegazione? – Guillaume

1

è necessario memorizzare i dati che si vogliono mostrano in una var pubblico e lasciate che il vostro Discussione chiamare un Runnable tramite Handler.post (eseguibile) Il codice nella corsa() Il metodo Runnable è in grado di accedere a Textview

2

Sono accessibili ma solo di sola lettura. Ciò che intendi è che vuoi attivare i cambiamenti da un thread sulle viste. Dal thread di lavoro (non-UI) queste modifiche non possono essere attivate, è necessario utilizzare .runOnUiThread() o utilizzare Handlers. Utilizzare questi nel punto in cui si desidera mostrare qualcosa, ad esempio aggiornare il TextView in .runOnUiThread(),

Esempio:

myThread = new Thread() 
     { 

      @Override 
      public void run() { 
       //yourOperation 
       MyActivity.this.runOnUiThread(new Runnable(){ 

        @Override 
        public void run() { 
         if(e!=null) 
         { 
          myTextView.setText("something"); 
         } 

        }}); 
       super.run(); 
      } 
     }; 
     myThread.start(); 
+0

è effettivamente possibile leggere solo una vista da un thread non-ui come hai detto? Sono interessato alla lettura di una bitmap da una vista utilizzando Bitmap drawingCache = view.getDrawingCache(), ma continuo a ricevere l'eccezione: CalledFromWrongThreadException: solo il thread originale che ha creato una gerarchia di viste può toccare le sue viste. – Giorgio

Problemi correlati