Autore Topic: Callback agganciata ad una classe  (Letto 719 volte)

Offline wlf

  • Utente normale
  • ***
  • Post: 367
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    Xperia
Callback agganciata ad una classe
« il: 14 Aprile 2017, 11:09:38 CEST »
0
Salve,
ho una Activity (MainActivity) che istanzia una classe (MyClass) che ha un un Listener (MyListener).
MainActivity quindi esegue un init() passando se stessa come listener.

Codice: [Seleziona]
MyListener.init(MainActivity.this)
In questa classe istanzio un Service (MyService) e vorrei che quest'ultimo comunichi con MyClass tramite un suo Listener (MyServiceListener).

Nel Service (MyService) ho creato un metodo init() per inizializzare il Listener.

Codice: [Seleziona]
    public void init(MyServiceListener listener){
        this.listener = listener;
    }


Ho delle difficoltà però ad agganciarlo a MyClass visto che non è un Activity. :(

Posso agganciare una Callback anche ad una classe oppure posso farlo solo agganciandomi ad una activity?

Grazie.

Offline tonno16

  • Utente storico
  • *****
  • Post: 1233
  • Respect: +60
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Callback agganciata ad una classe
« Risposta #1 il: 14 Aprile 2017, 11:49:46 CEST »
+1
Ciao. Io non ho capito molto bene cosa devi fare. Magari fai un piccolo diagramma.

In ogni caso puoi passare callback dove vuoi

Tip posto un esempio. Ho una classe/Activity che chiama una classeA responsabile di fare un upload di una foto su un server.
Quando l' upload viene completato, MyClassOrActivity vuole essere notificato dell' evento.

Codice (Java): [Seleziona]
    public class ClassA {
        void uploadPhoto(String url,OnUploadComplete calback){
            // some upload work with some time
            // boolean uploaded = UploadManager.upload("file,jpg",url);
            boolean uplaoded = true;
            calback.notifyUploadComplete(uplaoded);
        }
    }
   
    interface OnUploadComplete {
        void notifyUploadComplete(boolean ok);
    }
   
    public class MyActivityOrClass implements OnUploadComplete{
        public MyActivityOrClass(){
            uploadPhoto();
        }
       
        void uploadPhoto(){
            new ClassA().uploadPhoto("http://myserver.com",this);
        }


        @Override
        public void notifyUploadComplete(boolean uploadedOk) {
            Log.i("tag","upload: "+uploadedOk);
        }
    }

Offline wlf

  • Utente normale
  • ***
  • Post: 367
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    Xperia
Re:Callback agganciata ad una classe
« Risposta #2 il: 14 Aprile 2017, 14:45:15 CEST »
0
Grazie tonno16; nel frattempo ero già riuscito! ;)

Io però utilizzo due classi separate, una per l'interface e una per l'adapter.

Codice: [Seleziona]
    public class ClassA {
        OnUploadComplete listener;

        void init(OnUploadComplete listener) {
            this.listener = listener;             
        }

        void uploadPhoto(String url){
            // some upload work with some time
            // boolean uploaded = UploadManager.upload("file,jpg",url);
            boolean uplaoded = true;
            listener.notifyUploadComplete(uplaoded);
        }
    }

Codice: [Seleziona]
    public interface OnUploadComplete {
        void notifyUploadComplete(boolean ok);
    }

Codice: [Seleziona]
    public class MyActivityOrClass implements OnUploadComplete{
        public MyActivityOrClass(){
            uploadPhoto();
        }
       
        void uploadPhoto(){
            ClassA classA = new ClassA();
            classA().init(this);
            classA().uploadPhoto("http://myserver.com");
        }


        @Override
        public void notifyUploadComplete(boolean uploadedOk) {
            Log.i("tag","upload: "+uploadedOk);
        }
    }

Adesso però ho un errore più "noioso"

Citazione
Only the original thread that created a view hierarchy can touch its views.

Praticamente dalla MainActivity che implementa MyListener chiamo un adapter MyClass che implementa MyServiceListener che a sua volta istanzia un  service MyService. Questo avverte MyClass tramite il listener che mi sono connesso ed a sua volta MyClass avverte MainActivity della connessione visualizzandomelo nella UI con un semplice "TextView.SetText("Connected")".
Sulla UI vedo pure la scritta ma l'esecuzione si interrompe con l'errore che ho riportato.

A mio avviso è il thread originale (MainActivity) che modifica la UI, gli altri non hanno proprio accesso al widget, non fanno altro che avvertire in cascata. Prima tra MyService e MyClass invece di usare la callback utilizzavo un BroadcastReceiver attraverso un intent ed il problema non si presentava. Volevo sostituire il broadcastReceiver con la callback per fare un lavoro più pulito. :(

  • Mantenendo la callback tra MainActivity e MyClass e BroadcastReceiver tra MyClass e MyService funziona.
  • Mantenendo la callback tra MainActivity e MyClass e callback tra MyClass e MyService  non funziona.

Sembra quasi che una doppia callback in cascata gli dia fastidio. :(

Offline tonno16

  • Utente storico
  • *****
  • Post: 1233
  • Respect: +60
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Callback agganciata ad una classe
« Risposta #3 il: 14 Aprile 2017, 15:00:46 CEST »
0
Non lo so. In ogni caso io farei comunicare Service-Activity, e poi dall' Activity comunicherei con la classe

Offline wlf

  • Utente normale
  • ***
  • Post: 367
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    Xperia
Re:Callback agganciata ad una classe
« Risposta #4 il: 14 Aprile 2017, 15:37:15 CEST »
0
Scusa, ma come faccio a comunicare dal Service-->Activity se il service viene istanziato dalla classe?  ???

Comunque se nella MainActivity nel metodo implementato dalla callback di MyClass aggiungo "runOnUiThread" non ottengo l'errore:

Codice: [Seleziona]
    @Override
    public void onStatusChanged(final Status status) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {

                textViewStatus.setText(String.valueOf(status));

            }
        });
    }

Però sarei curioso di sapere come fare per comunicare direttamente da MyService con la MainActivity saltando MyClass in mezzo che ha istanziato il MyService. ;)
« Ultima modifica: 14 Aprile 2017, 15:58:52 CEST da wlf »

Offline tonno16

  • Utente storico
  • *****
  • Post: 1233
  • Respect: +60
    • Mostra profilo
  • Dispositivo Android:
    moto g
  • Play Store ID:
    Diego Tonini
  • Sistema operativo:
    OpenSuse
Re:Callback agganciata ad una classe
« Risposta #5 il: 14 Aprile 2017, 16:07:10 CEST »
0
Nativamente puoi farlo non ricordo io modo. Nella DOC ufficiale c'è. Senno dai un occhiata a eventbus

Offline iClaude

  • Utente normale
  • ***
  • Post: 311
  • Respect: +25
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S8
  • Sistema operativo:
    Windows 10
Re:Callback agganciata ad una classe
« Risposta #6 il: 17 Aprile 2017, 13:40:33 CEST »
0
Però sarei curioso di sapere come fare per comunicare direttamente da MyService con la MainActivity saltando MyClass in mezzo che ha istanziato il MyService. ;)

Lasciando stare se questo design è ottimale o meno (bisognerebbe vedere tutto il codice), limitandomi alla tua domanda direi:
- nel Service definisci un interfaccia con relativo metodo per impostare i listener
- la tua Activity deve implementare l'interfaccia
- quando crei MyClass gli passi un reference all'Activity e poi da MyClass passi questo reference al Service da usare come listener
Naturalmente devi anche prevedere la possibilità di annullare il listener quando l'Activity va in pausa o viene stoppata.