Autore Topic: Comunicazione tra Listener e UiThread  (Letto 139 volte)

Offline darioconcilio

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Comunicazione tra Listener e UiThread
« il: 10 Agosto 2017, 16:26:34 CEST »
0
Ciao a tutti,
rimetto a voi audaci, impavidi e saggi esperti (non sono sarcastico, sono umilmente prostrato a terra per la mia autostima generata da questo problema :-()

Dunque, ho creato un progetto con il servizio che permette di comunicare tramite BLE, ho creato quindi un servizio.
Dopodiché ho creato una classe chiamata BLEHelper dove ho metto tutto quello che serve per: ricercare, connettere, inviare, ricevere etc..

Ora sono nella MainActivity e volevo fare delle prove.
Ho messo nella BLEHelper una serie di interfacce "Listener" per poter inviare alla MainActivity una serie di eventi. Ma mi trovo a scoprire (perché sono un piccolo e indigesto sviluppatore per Android penso...) che dopo aver implementato i listener della BLEHelper all'interno della MainActivity, tutto quello che viene fatto all'interno degli eventi sono in un thread parallelo e non nel thread principale.

Quindi se voglio fare questo:
Codice: [Seleziona]
@Override
    public void onStartSearchingDevices() {
        progress = new ProgressDialog(this);
        progress.setMessage("Ricerca dispositivi...");
        progress.setIndeterminate(true);
        progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);

        progress.show();
    }

    @Override
    public void onFoundDevices(List<BluetoothDevice> devices) {

        progress.dismiss();

        String message = "";
        if (devices.size() > 0)
            message = String.format("Il BLE trovato si chiama %s", devices.get(0).getName());
        else
            message = "Non sono stati trovati dispositivi";

        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }

Non appare la ProgressDialog ne il Toast message, se li eseguo all'interno del UiThread funziona.....
Ora, come posso definire le interfacce della classe BLEHelper in modo da evitare questo? Vorrei arrivare al codice qui sopra indicato.
Devo iniettare in qualche modo la View corrente nelle interfacce? Si può? Se si, come?

Abbiate pazienza ma mi sono convertito poco tempo fa al mondo Java/Android, potrei aver detto qualche castroneria, che nel modo C# ha senso qui magari no. Chiedo scusa in anticipo.

Ho allegato i vari packages.

Offline iClaude

  • Utente normale
  • ***
  • Post: 257
  • Respect: +19
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S8
  • Sistema operativo:
    Windows 10
Re:Comunicazione tra Listener e UiThread
« Risposta #1 il: 10 Agosto 2017, 18:14:01 CEST »
0
Specifica meglio che tipo di servizio hai creato e come esegui le operazioni al suo interno...

Offline darioconcilio

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Re:Comunicazione tra Listener e UiThread
« Risposta #2 il: 10 Agosto 2017, 18:39:40 CEST »
0
Ho allegato tutto,
il servizio permette di gestire il BLE del dispositivo.
Il servizio in sé però non è in dubbio, gestisco già il tutto in un altro progetto senza problemi, ma senza incapsulare le chiamate BLE all'interno di una classe.

La mia mancanza di esperienza mi ha portato a  questo post, in quanto non so come gestire gli eventi della classe BLEHelper, in modo da non dover scrivere codice, nella MainActivity, per gestire l'accesso al UiThread.

Probabilmente ho solo bisogno di capire alcuni concetti che non mi sono ancora chiari.
Volevo allegare l'intero progetto ma sono 30MB, per questo ho allegato lo zip con le classi chiave.

La classe RBLService usa le classi base per la comunicazione BLE su un thread sempre attivo, sfruttando la libreria BluetoothManager e BluetoothGatt eseguendo una comunicazione stile "Chat", sto sfruttando questo metodo per avere una sorta di comunicazione di array di byte simile alla comunicazione seriale


Post unito: 10 Agosto 2017, 19:12:01 CEST
Ok nel mentre.... ho trovato una mia soluzione.

Al costruttore della classe BLEHelper gli passo l'activity.
In questo modo ogni volta che deve "lanciare" un evento di qualche listener, basta che faccio così.
Codice: [Seleziona]
mActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        mCommunicationListener.onFoundDevices(mDevices);
                    }
                });

Questo mi permette di mantene codice pulito nella MainActivity.

Grazie comunque. Se avete soluzioni più eleganti, pendo dalle vostre labbra.

A presto.
« Ultima modifica: 10 Agosto 2017, 19:12:01 CEST da darioconcilio, Reason: Merged DoublePost »

Offline iClaude

  • Utente normale
  • ***
  • Post: 257
  • Respect: +19
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S8
  • Sistema operativo:
    Windows 10
Re:Comunicazione tra Listener e UiThread
« Risposta #3 il: 10 Agosto 2017, 19:21:57 CEST »
0
Preciso che mi sono limitato ai due metodi che hai riportato (onStartSearchingDevices, onFoundDevices): non ho esaminato tutto il codice, all'interno del quale ho notato cmq alcuni problemi (sarebbe meglio utilizzare un WeakReference all'Activity, non è gestita l'ipotesi di cambio di configurazione dell'Activity, ecc.).

Cmq sia, quei due metodi sono chiamati da un thread separato, quindi come hai già intuito è quello il problema.
Devi chiamarli dal thread della UI.
Puoi tentare una cosa del tipo:

Codice (Java): [Seleziona]
            mActivity.runOnUiThread(new Runnable() {
                    public void run() {
                        mCommunicationListener.onStartSearchingDevices();
                    }});

Ah, mentre scrivevo non ho notato la tua modifica...  :-)
« Ultima modifica: 10 Agosto 2017, 19:23:35 CEST da iClaude »

Offline darioconcilio

  • Nuovo arrivato
  • *
  • Post: 13
  • Respect: 0
    • Mostra profilo
Re:Comunicazione tra Listener e UiThread
« Risposta #4 il: 10 Agosto 2017, 22:43:11 CEST »
0
Grazie comunque.
Per la WeakReference non ho ancora molta dimestichezza, anche se ho letto qualcosa in merito.
Dovrei dichiarare la mia mActivity come WeakReference<Activity> in modo da non farla considerare dal garbage collector giusto?

Offline iClaude

  • Utente normale
  • ***
  • Post: 257
  • Respect: +19
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S8
  • Sistema operativo:
    Windows 10
Re:Comunicazione tra Listener e UiThread
« Risposta #5 il: 11 Agosto 2017, 17:31:46 CEST »
0
Servirebbe per il contrario, cioè fare in modo che sia garbage collected.
Se affidi le operazioni di un Activity ad classe di utilità esterna devi considerare:
- possibili memory leaks se passi strong reference a Context o altri oggetti simili
- il ciclo di vita dell'Activity deve essere coordinato con la classe esterna, specialmente se lanci thread secondari.