Autore Topic: Gestione di un listener in un thread separato  (Letto 398 volte)

Offline dacplus

  • Nuovo arrivato
  • *
  • Post: 9
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    HTC Dsisre HD
Gestione di un listener in un thread separato
« il: 18 Maggio 2014, 22:19:41 CEST »
0
Buongiorno,

vorrei cercare di illustrarvi il mio problema sperando che riusciate ad aiutarmi con la soluzione:

In un thread (che nel caso specifico è il UI ma potrebbe tranquillamente essere un thread qualsiasi) ho un metodo che fa una chiamata asincrona ad un processo una serie di metodi che fanno delle chiamate asicrone ad un server via HTTP. Il risultato viene catturato tramite un listenerer e mostrato nell'activity:

Codice (Java): [Seleziona]
public class MainActivity extends Activity {

   TextView tv;

   . . .

   public void callAsyncOperation(View v) {
      performAsyncOperation( new AsyncListener() { // chiamata HTTP
         @Override
         public void onResult(String result) {
            tv.setText(result);
         }
      });
   }
}

Ovviamente questa operazione nuon può funzionare perchè sto cercando di aggiornare il testo di una Textview nel main UI da un thread diverso e ricevo questo errore:
Codice: [Seleziona]
05-18 22:09:56.690    3809-3817/net.igloo.sledexample E/JavaBinder﹕ *** Uncaught remote exception!  (Exceptions are not yet supported across processes.)
    android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRoot.checkThread(ViewRoot.java:3165)
            at android.view.ViewRoot.requestLayout(ViewRoot.java:677)
            at android.view.View.requestLayout(View.java:8507)
            at android.view.View.requestLayout(View.java:8507)
            at android.view.View.requestLayout(View.java:8507)
            at android.view.View.requestLayout(View.java:8507)
            at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:257)
            at android.view.View.requestLayout(View.java:8507)
            at android.widget.ScrollView.requestLayout(ScrollView.java:1299)
            at android.view.View.requestLayout(View.java:8507)
            at android.widget.TextView.checkForRelayout(TextView.java:5795)
            at android.widget.TextView.setText(TextView.java:2827)
            at android.widget.TextView.setText(TextView.java:2695)
            at android.widget.TextView.setText(TextView.java:2670)
            at net.igloo.sledexample.MainActivity$1.onResult(MainActivity.java:88)
            at net.igloo.sled2.service.ServiceHelper$1.operationSuccess(ServiceHelper.java:120)
            at net.igloo.sled2.service.RestCallback$Stub.onTransact(RestCallback.java:52)
            at android.os.Binder.execTransact(Binder.java:320)
            at dalvik.system.NativeStart.run(Native Method)

Eseguendo il codice all'interno del MainThread aggiro il problema:
Codice (Java): [Seleziona]
public void callAsyncOperation(View v) {
      performAsyncOperation( new AsyncListener() {
         @Override
         public void onResult(String result) {
            new Thread() {
               public void run() {
                  MainActivity.this.runOnUiThread(new Runnable() {
                     @Override
                     public void run() {
                        tv.setText(result);
                      }
                   });
                }
             }.start();
          }
      });
   }

ma il codice diventa pessimo e illegibile, quindi vorrei evitare a monte il problema gestendo questo passaggio direttamente in fase di inserimento del risultato nel listener così da poter chiamare semplicemente l'operazione performAsyncOperation(listener) in qualsiasi thread.

Qualcuno ha un idea per aiutarmi ad uscire da questo empasse?

Grazie
« Ultima modifica: 19 Maggio 2014, 09:24:22 CEST da dacplus »

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Gestione di un listener in un thread separato
« Risposta #1 il: 19 Maggio 2014, 08:02:17 CEST »
0
Credo di non aver ben capito il codice e la sua descrizione, ma ti faccio due domande:

1) Sicuro di fare una "chiamata asincrona ad un processo"? Che io sappia non c'è modo di comunicare direttamente tra "processi", Probabilmente intendevi un "thread".

2) Se la tua necessità è ricevere indietro un evento (e dati) dal worker thread, un modo semplice e ben leggibile consiste nel passare al thread il riferimento all'handler dell'activity, quindi da thread spedire un "message" all'handler.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline dacplus

  • Nuovo arrivato
  • *
  • Post: 9
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    HTC Dsisre HD
Re:Gestione di un listener in un thread separato
« Risposta #2 il: 19 Maggio 2014, 09:33:44 CEST »
0
Grazie della risposta.
Ho modificato un po il topic per cercare di renderlo un po più chiaro.
In realtà io sto cercando di sviluppare un piccolo framework per comunicare con un server mediante HTTP seguendo il modello del Google I/O del 2010 (http://www.youtube.com/watch?v=xHXn3Kg2IQE).

Per questa ragione vorrei lasciare all'utilizzatore finale un metodo ( per esempio risorsa.get() ) che restituisca direttamente il risultato senza che si preoccupi di Thread e Handler, in quanto già gestiti dal Framwork stesso.

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Gestione di un listener in un thread separato
« Risposta #3 il: 19 Maggio 2014, 10:37:36 CEST »
0
In realtà io sto cercando di sviluppare un piccolo framework per comunicare con un server mediante HTTP seguendo il modello del Google I/O del 2010 (http://www.youtube.com/watch?v=xHXn3Kg2IQE).
Per questa ragione vorrei lasciare all'utilizzatore finale un metodo ( per esempio risorsa.get() ) che restituisca direttamente il risultato senza che si preoccupi di Thread e Handler, in quanto già gestiti dal Framwork stesso.

Se stai sviluppando un framework, ti merita dare un'occhiata a come hanno implementato questa funzionalità altri framework analoghi, dato che sono più o meno tutti open source. Puoi vedere ION di Koush, ma anche Picasso per le immagini, e tanti altri.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store