Autore Topic: Problema worker thread, handler e aggiornamento textview  (Letto 606 volte)

Offline panto91

  • Nuovo arrivato
  • *
  • Post: 14
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Tab S 10.5
  • Sistema operativo:
    Mac OS X 10.9
Problema worker thread, handler e aggiornamento textview
« il: 10 Novembre 2015, 01:26:28 CET »
0
Ciao a tutti,
sto portando avanti un progetto in cui attualmente sono bloccato. Mi spiego meglio ... ho creato un'activity che al suo avvio dovrebbe creare un thread "di lavoro" che si dovrebbe occupare di effettuare la connessione ad un socket server e successivamente entrare in un loop infinito in cui prende dei dati che il server socket invia di continuo ...

Attualmente il codice non effettua neanche la connessione al socket e francamente non capisco il perchè ... non vedo l'errore.

Codice (Java): [Seleziona]
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;

import static com.icmweightcontrol.R.id.actual_weight;

/**
 * Created by Francesco on 08/11/15.
 */

public class liveweight_activity extends Activity {

    Thread thread;
    Handler handler;
    TextView myTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_liveweight);
        myTextView = (TextView) findViewById(actual_weight);
        thread = new Thread(new MyThread());
        thread.start();
        handler = new Handler() {
            public void handleMessage(Message msg) {
                myTextView.setText(msg.arg1 + "\nKg");
            }
        };
    }
   
    public class MyThread implements Runnable {
        private Socket s;
        private static final String serverip = "192.168.1.7";
        public void run() {
        Message message = Message.obtain();
        try {
            InetAddress wifiserver = InetAddress.getByName(serverip);
            s = new Socket(wifiserver, 8899);
        }catch (IOException e){
            e.printStackTrace();
        }

        while (true) {
            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
                String stringmessage = reader.readLine();
                message.arg1 = Integer.parseInt(stringmessage);
            }catch (IOException e) {
                e.printStackTrace();
            }
            handler.sendMessage(message);
            }
        }
    }
   
}

L'applicazione compila senza problemi e Android Studio non rileva errori.

Sono nelle vostre mani.

Grazie

Francesco

Offline panto91

  • Nuovo arrivato
  • *
  • Post: 14
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Tab S 10.5
  • Sistema operativo:
    Mac OS X 10.9
Re:Problema worker thread, handler e aggiornamento textview
« Risposta #1 il: 11 Novembre 2015, 20:02:04 CET »
0
Ciao a tutti, ho aggiornato così la connessione al socket e funziona bene. Però non mi si aggiorna la textview ... Come posso risolvere?

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

    Thread thread;
    Handler handler;
    TextView myTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_liveweight);
        myTextView = (TextView) findViewById(actual_weight);
        thread = new Thread(new MyThread());
        thread.start();
        handler = new Handler() {
            public void handleMessage(Message msg) {
                myTextView.setText(msg.arg1 + "\nKg");
            }
        };
    }

    public class MyThread implements Runnable {
        private static final String serverip = "192.168.1.7";
        public void run() {
            Message message = Message.obtain();
            try {
                InetAddress wifiserver = InetAddress.getByName(serverip);
                Socket s = new Socket(wifiserver, 8899);
                while (true) {
                        BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
                        String stringmessage = reader.readLine();
                        message.arg1 = Integer.parseInt(stringmessage);
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
            handler.sendMessage(message);
        }
    }
}

Inoltre Android Studio mi comunica nel pezzo di codice
Codice (Java): [Seleziona]
    handler = new Handler() {
            public void handleMessage(Message msg) {
                myTextView.setText(msg.arg1 + "\nKg");
            }
        };

questo errore: "This Handler class should be static or leaks might occur"

Come posso risolvere?

Vi prego ... qualcuno che mi aiuti ... non riesco a risolvere ... :(

Offline iClaude

  • Utente normale
  • ***
  • Post: 202
  • Respect: +13
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5
  • Sistema operativo:
    Windows 10
Re:Problema worker thread, handler e aggiornamento textview
« Risposta #2 il: 12 Novembre 2015, 12:13:35 CET »
0
Il ciclo while(true) è infinito e non si arriva mai al punto di invio del messaggio, a meno che non venga lanciata un'eccezione.

Riguardo al warning di Android Studio, un handler definito come classe interna non statica o anonima può causare memory leaks in quanto tiene un riferimento implicito alla Activity esterna, e in certi casi potrebbe vivere oltre la morte della Activity (es se fai un postDelayed).
La soluzione è molto semplice: dichiararlo come classe static.

Offline panto91

  • Nuovo arrivato
  • *
  • Post: 14
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Galaxy Tab S 10.5
  • Sistema operativo:
    Mac OS X 10.9
Re:Problema worker thread, handler e aggiornamento textview
« Risposta #3 il: 12 Novembre 2015, 18:06:33 CET »
0
Il ciclo while(true) è infinito e non si arriva mai al punto di invio del messaggio, a meno che non venga lanciata un'eccezione.

Riguardo al warning di Android Studio, un handler definito come classe interna non statica o anonima può causare memory leaks in quanto tiene un riferimento implicito alla Activity esterna, e in certi casi potrebbe vivere oltre la morte della Activity (es se fai un postDelayed).
La soluzione è molto semplice: dichiararlo come classe static.

Quindi posso dichiararlo dopo a tutto come classe static e poi dopo come la richiamo?

Ora ho risolto mettendo l invio del messaggio all'interno del ciclo infinito.
Ma dopo che viene inviato e visualizzato il primo messaggio ... se ne invio un'altro l'app crasha. come posso risolvere?
Metto qui sotto il codice (ultima versione) del thread:
Codice (Java): [Seleziona]
 public class MyThread implements Runnable {
        private static final String serverip = "192.168.10.14";
        public void run() {
            Message message = Message.obtain();
            try {
                InetAddress wifiserver = InetAddress.getByName(serverip);
                Socket s = new Socket(wifiserver, 8899);
                while (true) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
                    String stringmessage = reader.readLine()+"\r";
                    message.obj = stringmessage;
                    // message.arg1 = Integer.parseInt(stringmessage);
                    handler.sendMessage(message);
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }

Offline iClaude

  • Utente normale
  • ***
  • Post: 202
  • Respect: +13
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S5
  • Sistema operativo:
    Windows 10
Re:Problema worker thread, handler e aggiornamento textview
« Risposta #4 il: 12 Novembre 2015, 20:06:39 CET »
+1
Non è possibile riutilizzare lo stesso Message come hai fatto tu. Devi ogni volta (cioè all'interno del ciclo while) ottenere un nuovo Message con Message.obtain(): internamente Android utilizza un pool di messaggi riciclando quelli non più utilizzati se necessario, quindi non devi preoccuparti di ciò.

Per quanto riguarda il problema degli Handler e memory leaks la questione è un tantino più complicata, perchè definendo l'Handler come classe statica, cioè una top level class, è necessario passare ad esso un reference alla Activity, e più precisamente è necessario utilizzare un weak reference per evitare memory leaks.
E' spiegato tutto in dettaglio in questa guida:
How to Leak a Context: Handlers & Inner Classes | Android Design Patterns