Autore Topic: Dove metto il ProgressDialog?  (Letto 714 volte)

Offline Alhazred

  • Utente junior
  • **
  • Post: 50
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Asus Zenfone 2 Laser ZE550KL
  • Sistema operativo:
    Windows 10 Home 64bit
Dove metto il ProgressDialog?
« il: 02 Marzo 2012, 10:51:43 CET »
0
Premetto che so come va inserito, l'ho fatto ed appare.
Il mio problema è dove metterlo e dove rimuoverlo.
Ho provato già in diversi punti, ma ho dei comportamenti strani.
Intanto un po' di codice (tagliando le parti non importanti)

Questa Activity mostra una form con 4 campi di testo e 3 gruppi RadioButton (3, 3 e 2 bottoni), infine un bottone per l'invio dei dati.
Alla pressione del bottone vengono presi i dati dalla form, verificato che siano corretti quelli dei campi di testo e se è tutto ok vengono messi in un bundle e spediti ad un'altra Activity.
Non fa altro.
Codice: [Seleziona]
//package e import

public class MyApp extends Activity {
       
        //dichiarazione variabili
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //PREPARAZIONE PICKER E CAMPI AUTOCOMPLETE

        //pulsante per avviare la ricerca
        final Button button = (Button) findViewById(R.id.button_search);
        button.setOnClickListener(new View.OnClickListener() {
                //operazioni da effettuare al click
                public void onClick(View button) {
                       
                        //ISTRUZIONI PER PRENDERE I VALORI DAI CAMPI DELLA FORM
                                //E CONTROLLI SULL'INPUT
                   
                    //controllo i dati dei campi di testo
                    if(!in_array(stations,stationFrom) || !in_array(stations,stationTo))
                    {
                            /*************************/
                    }
                                //DIVERSI ALTRI CHECK
                    else {
                            //intent che avviera l'activity con l'elenco dei percorsi trovati
                            Intent intent = new Intent(button.getContext(), RoutesListActivity.class);

                            Bundle b = new Bundle();
                        b.putString("stationFrom", stationFrom);
                        //altri campi

                        intent.putExtras(b);
                        startActivity(intent);
                    }
            }
        });
 
        updateDisplay();
    }
}

Questa Activity prende i dati provenienti dalla precedente, costruisce una richiesta http con parametri POST e l invia ad uno script che ho sul mio sito.
Il mio sito fa delle cose col database e restituisce una stringa in formato JSON all'app.
A questo punto l'app verifica che ci siano dei percorsi nella stringa ricevuta, con questi genera una ListView e la mostra.
Fine.
Codice: [Seleziona]
//package e import

public class RoutesListActivity extends Activity implements OnItemClickListener {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.routes_list);
       
        Bundle b = getIntent().getExtras();
        String stationFrom         = b.getString("stationFrom");
        //prendo gli altri campi
               
        //chiamata alla funzione postData per inviare la richiesta al server
        postData(stationFrom,stationTo,date,time,searchBy,type,orderBy);
    }
   
    public void postData(String stfrom, e gli altri parametri) {
       
            if(isNetworkAvailable())
            {
                    // Crea un oggetto HttpClient
                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost("http://www.miosito.it/android/myapp/script.php");
       
                //parametri da inviare tramite POST
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
                nameValuePairs.add(new BasicNameValuePair("from", stfrom));
                //appende altri dati
               
                // Url Encoding the POST parameters
                try {
                    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                }
                catch (UnsupportedEncodingException e) {
                        /********/
                }
         
                // HTTP Request
                try
                {
                    HttpResponse response = httpclient.execute(httppost); //invio la richiesta al server
                    HttpEntity entity = response.getEntity();
                   
                    if (entity != null) {
                            //elaborazione dati ricevuti
                            if(result.contains("sections")) { //è stato trovato almeno un percorso

                                            //elaborazione dati ricevuti dallo script e creazione di una ListView

                            }
                    }
                }
                catch (ClientProtocolException e){ bla bla }
            }
            else { messaggio per percorsi non trovati }
    }
}

In tutto questo, appena tappo il pulsante della form, la mia app resta ferma lì per un po', poi cambia schermata e mostra la ListView della seconda activity.
Nonostante resti ferma sulla prima schermata, suppongo che in realtà stia perdendo tempo con la comunicazione con lo script php che si trova nella seconda activity.

Ecco cosa ho provato:
- PrograssDialog subito prima dell'invio della richiesta http e il cancel() dopo la chiusura dello straming, il dialog non appare

- dialog nella prima activity prima di startActivity(intent) il dialog appare, poi si passa alla seconda activity regolarmente, il problema è che se torno indietro alla prima activity, il dialog è ancora lì.

- dialog nella prima activity prima di startActivity(intent) e cancel() dopo tale istruzione, il dialog non appare

Sembra quasi che debba mettere lo show() nella prima activity e il cancel() nella seconda, ma non posso referenziare nella seconda il dialog che si trova nella prima (o quantomeno non lo so fare).

Come devo fare?

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:Dove metto il ProgressDialog?
« Risposta #1 il: 02 Marzo 2012, 11:04:35 CET »
+1
Premetto che so come va inserito, l'ho fatto ed appare.
Il mio problema è dove metterlo e dove rimuoverlo.
Ho provato già in diversi punti, ma ho dei comportamenti strani.
...
Come devo fare?

L'approccio Android a questo genere di problematiche è abbastanza diverso dalla soluzione che stai implementando, che anzi è fortemente sconsigliata.

Il concetto fondamentale è che in Android il thread principale è quella della UI e in tale thread NON devono essere fatte girare operazioni lunghe (come accessi alla rete, etc), pena il Force Close dell'applicazione da parte del sistema operativo dopo un timeout di qualche secondo. La onCreate in cui tu esegui l'accesso alla rete gira nel thread di UI.

Il modo corretto di farlo è in un thread a parte, che però deve essere in qualche modo sincronizzato con il thread di UI per interagire con una progressDialog (che gira nel thread di UI). Però, poichè è una cosa molto comune, hanno predisposto gli AsyncTask, che rendono particolarmente semplice l'avvio di operazioni in thread secondari e l'interazione con la UI.

Questo tutorial ( [facile] HttpBookSearch: AsyncTask, HttpClient, XML parsing, ProgressDialog - Android Developers Italia ) dovrebbe fornire un buon punto di partenza. Che poi è una delle primissime applicazioni che ho fatto, fa una chiamata con HttpClient con un AsyncTask e gestisce la ProgressDialog.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Alhazred

  • Utente junior
  • **
  • Post: 50
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Asus Zenfone 2 Laser ZE550KL
  • Sistema operativo:
    Windows 10 Home 64bit
Re:Dove metto il ProgressDialog?
« Risposta #2 il: 02 Marzo 2012, 13:03:55 CET »
0
Grazie, sto provando ad applicare il metodo del tutorial alla mia app.
Non ho capito dove impostare i parametri da passare ad AsyncTask<String,String,String>

Offline Alhazred

  • Utente junior
  • **
  • Post: 50
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Asus Zenfone 2 Laser ZE550KL
  • Sistema operativo:
    Windows 10 Home 64bit
Re:Dove metto il ProgressDialog?
« Risposta #3 il: 02 Marzo 2012, 14:55:31 CET »
0
Ok, penso di aver capito.

C'è un'altra cosa.
Seguendo il tuo tutorial, nella classe AsyncTask ci sono questi due metodi
Codice: [Seleziona]
@Override
    protected void onProgressUpdate(String... values) {
       // aggiorno la progress dialog
       pd.setMessage(values[0]);
    }

    @Override
    protected void onPostExecute(String result) {
       // chiudo la progress dialog
       pd.dismiss();
    }
a me sui pd da un errore non riuscendo a risolvere le variabili, se aggiungo all'inizio della classe
private ProgressDigalog pd;
gli errori spariscono, ma a runtime ovviamente ho un NullPointerException perché non puntano al ProgressDialog definito nel thread principale.

Questa è la mia AsyncTask
Codice: [Seleziona]
//package e import

public class HttpGetTask extends AsyncTask<String[],String,String>  {

        @Override
    protected String doInBackground(String[]... params) {

         String result = "";
          // aggiorno la progress dialog
          publishProgress("Creating HTTP client and query...");
         
          //Crea un oggetto HttpClient
          HttpClient httpclient = new DefaultHttpClient();
          HttpPost httppost = new HttpPost("http://www.miosito.it/android/myapp/script.php");
         
        //parametri da inviare tramite POST
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
                nameValuePairs.add(new BasicNameValuePair("from", params[0][0].toString()));
                //altri parametri
               
             // Url Encoding the POST parameters
                try {
                    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                }
                catch (UnsupportedEncodingException e) {
                        Log.w("MYAPP", "Exception: "+e.toString());
                }
         
                // Making HTTP Request
                try {
                    HttpResponse response = httpclient.execute(httppost); //invio la richiesta al server
                    HttpEntity entity = response.getEntity();
                   
                    if (entity != null) {
                            InputStream instream = entity.getContent(); //prendo lo streaming di risposta
                            result = convertStreamToString(instream); //Percorsi in formato JSON
                            instream.close(); //chiusura dello stream
                    }
                }
                catch (ClientProtocolException e) {
                        Log.w("MYAPP", "Exception: "+e.toString());
                }
                catch (IOException e) {
                        Log.w("MYAPP", "Exception: "+e.toString());
                }
               
                return result;
       }
     

    @Override
    protected void onProgressUpdate(String... values) {
       // aggiorno la progress dialog
       pd.setMessage(values[0]);
    }

    @Override
    protected void onPostExecute(String result) {
       // chiudo la progress dialog
       pd.dismiss();
    }

     //metodo convertStreamToString()
 }
Come risolvo questa cosa di pd?

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:Dove metto il ProgressDialog?
« Risposta #4 il: 02 Marzo 2012, 15:23:29 CET »
+1
E' perchè io nel tutorial ho preso una scorciatoia: ho creato la classe dell'AsyncTask internamente alla classe dell'Activity, per cui essendo pd definita come variabile privata all'activity, potevo referenziarla anche nell'AsyncTask. Mettendo la classe dell'AsyncTask in un file a parte, sarebbe necessario passargli il riferimento alla progress dialog (ad esempio nel costruttore) e memorizzarlo in una variabile membro per poterla usare.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Alhazred

  • Utente junior
  • **
  • Post: 50
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Asus Zenfone 2 Laser ZE550KL
  • Sistema operativo:
    Windows 10 Home 64bit
Re:Dove metto il ProgressDialog?
« Risposta #5 il: 02 Marzo 2012, 15:43:24 CET »
0
Perfetto, adesso funziona!
Grazie mille :-)