CERCA
PER MODELLO
FullScreen Chatbox! :)

Utente del giorno: 9mm con ben 3 Thanks ricevuti nelle ultime 24 ore
Utente della settimana: 9mm con ben 8 Thanks ricevuti negli ultimi sette giorni
Utente del mese: 9mm con ben 29 Thanks ricevuti nell'ultimo mese

Visualizzazione dei risultati da 1 a 6 su 6
Discussione:

Problema gestione AsyncTask tra client (App) e server (MySQL)

Se questa discussione ti è stata utile, ti preghiamo di lasciare un messaggio di feedback in modo che possa essere preziosa in futuro anche per altri utenti come te!
  1. #1
    Baby Droid


    Registrato dal
    Jan 2011
    Messaggi
    22

    Ringraziamenti
    2
    Ringraziato 0 volte in 0 Posts
    Predefinito

    Problema gestione AsyncTask tra client (App) e server (MySQL)

    Ciao a tutti,
    sono abbastanza nuovo alla programmazione android 4.3 e stavo cercando di crearmi una piccola applicazione Android (lato client) che fosse in grado di collegarsi ad un server web per memorizzare delle informazioni.
    La logica che implemento è questa:

    APP Android <-> HTTP <-> PHP <-> MySQL
    Dove <-> sono operazioni di scrittura/lettura.

    Per lanciare le operazioni di lettura o scrittura sfrutto gli AsyncTask che in background contattano in HTTP il server. Il tutto funziona bene, ma ho riscontrato un problema piuttosto fastidioso in fase di scrittura con gli AsyncTask che mi sta facendo dannare e non sono ancora riuscito a trovare una soluzione.

    La situazione è la seguente:
    L'Activity (PADRE) contiene un AsyncTask che visualizza la lista dei valori che legge dal server. (PADRE) ha un bottone che lancia un'Activity (FIGLIO) che è un form di inserimento valori. Quando l'utente vuole salvare i dati appena scritti nel form del (FIGLIO) schiacciando un bottone "OK", (FIGLIO) lancia il suo AsyncTask che accede al server e scrive (L'utente vuole inserire la parola "Dato1"). Al termine dell'operazione (1secondo al max) l'AsyncTask del (FIGLIO) si chiude e termina anche l'activity (FIGLIO). Il (PADRE) se ne accorge e rilancia il sua AsyncTask per aggiornare la lista con la nuova info.

    Fin qua tutto bene, ma se decido di ricominciare il giro per effettuare una nuova registrazione -quindi clicco il bottone di (PADRE) e rifaccio il giro- in fase di nuova scrittura l'AsyncTask del (FIGLIO) scrive correttamente i nuovi dati (L'utente ha scritto "Dato2"), ma in backgroud rigira anche il vecchio AsyncTask del (FIGLIO) -cioè quello del giro precedente con le vecchie informazioni (cioè "Dato1")- e quindi mi ritrovo nel DB il nuovo dato ("Dato2") e il vecchio ("Dato1") che è stato riscritto!

    In questo momento nel DB avrei:
    "Dato1" <- scritto al primo giro
    "Dato2" <- scritto al secondo giro
    "Dato1" <- riscritto al secondo giro : vuol dire che il vecchio AsyncTask ha rigirato!

    Spero di essere stato abbastanza chiaro sul mio problema. Rimane attivo il vecchio AsyncTask che non viene distrutto (sebbene cerchi di farlo) e che probabilmente viene rilanciato quando viene generato il secondo dall'Activity (FIGLIO).
    Il mio obiettivo è impedire questa cosa e non riesco a capire cosa fare.
    Avete dei suggerimenti?


    Note:
    -Ho provato a disabilitare l'AsyncTask con il comando task.cancel(true) e poi controllando questo valore in caso di rigiri ma senza esito buoni.
    -Il corpo dell'AsyncTask è semplice e sequenziale, cioè non effettua cicli. Scrive ed esce.
    Ultima modifica di AnderAndroid; 08-07-14 alle 10:32

  2.  
  3. #2
    Androidiano L'avatar di iClaude76


    Registrato dal
    Oct 2012
    Località
    Trento
    Messaggi
    207
    Smartphone
    Galaxy S3, Nexus 7, G. Tab 2 7

    Ringraziamenti
    1
    Ringraziato 27 volte in 25 Posts
    Predefinito

    Quote Originariamente inviato da AnderAndroid Visualizza il messaggio
    Ciao a tutti,
    sono abbastanza nuovo alla programmazione android 4.3 e stavo cercando di crearmi una piccola applicazione Android (lato client) che fosse in grado di collegarsi ad un server web per memorizzare delle informazioni.
    La logica che implemento è questa:

    APP Android <-> HTTP <-> PHP <-> MySQL
    Dove <-> sono operazioni di scrittura/lettura.

    Per lanciare le operazioni di lettura o scrittura sfrutto gli AsyncTask che in background contattano in HTTP il server. Il tutto funziona bene, ma ho riscontrato un problema piuttosto fastidioso in fase di scrittura con gli AsyncTask che mi sta facendo dannare e non sono ancora riuscito a trovare una soluzione.

    La situazione è la seguente:
    L'Activity (PADRE) contiene un AsyncTask che visualizza la lista dei valori che legge dal server. (PADRE) ha un bottone che lancia un'Activity (FIGLIO) che è un form di inserimento valori. Quando l'utente vuole salvare i dati appena scritti nel form del (FIGLIO) schiacciando un bottone "OK", (FIGLIO) lancia il suo AsyncTask che accede al server e scrive (L'utente vuole inserire la parola "Dato1"). Al termine dell'operazione (1secondo al max) l'AsyncTask del (FIGLIO) si chiude e termina anche l'activity (FIGLIO). Il (PADRE) se ne accorge e rilancia il sua AsyncTask per aggiornare la lista con la nuova info.

    Fin qua tutto bene, ma se decido di ricominciare il giro per effettuare una nuova registrazione -quindi clicco il bottone di (PADRE) e rifaccio il giro- in fase di nuova scrittura l'AsyncTask del (FIGLIO) scrive correttamente i nuovi dati (L'utente ha scritto "Dato2"), ma in backgroud rigira anche il vecchio AsyncTask del (FIGLIO) -cioè quello del giro precedente con le vecchie informazioni (cioè "Dato1")- e quindi mi ritrovo nel DB il nuovo dato ("Dato2") e il vecchio ("Dato1") che è stato riscritto!

    In questo momento nel DB avrei:
    "Dato1" <- scritto al primo giro
    "Dato2" <- scritto al secondo giro
    "Dato1" <- riscritto al secondo giro : vuol dire che il vecchio AsyncTask ha rigirato!

    Spero di essere stato abbastanza chiaro sul mio problema. Rimane attivo il vecchio AsyncTask che non viene distrutto (sebbene cerchi di farlo) e che probabilmente viene rilanciato quando viene generato il secondo dall'Activity (FIGLIO).
    Il mio obiettivo è impedire questa cosa e non riesco a capire cosa fare.
    Avete dei suggerimenti?


    Note:
    -Ho provato a disabilitare l'AsyncTask con il comando task.cancel(true) e poi controllando questo valore in caso di rigiri ma senza esito buoni.
    -Il corpo dell'AsyncTask è semplice e sequenziale, cioè non effettua cicli. Scrive ed esce.
    Ciao, l'AsyncTask dovrebbe essere eseguito una volta sola, a meno che tu non lo faccia ripartire.
    Ti consiglio di verificare con un Log i dati che scrivi sul server: magari banalmente sono i dati scritti la seconda volta ad essere sbagliati.

  4. #3
    Baby Droid


    Registrato dal
    Jan 2011
    Messaggi
    22

    Ringraziamenti
    2
    Ringraziato 0 volte in 0 Posts
    Predefinito

    Purtroppo ho provato a controllare ma i dati scritti sono corretti, ma per qualche strano motivo al secondo click sul bottone rigirano anche AsyncTask vecchi e che ormai dovrebbero essere stati rilasciati.

    Provo ad allegare un esempio di codice funzionante che soffre di questa cosa:

    Main Activity: Ha giusto un bottone ed un form da compilare. Quando si pigia il bottone quello che è scritto nel form viene messo sul db attraverso l'AsyncTask.
    codice:
    package com.example.testscritturamysql;
    
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.View;
    import android.widget.EditText;
     
    public class MainActivity extends Activity {
    	  
    	AsyncTask<String, Void, String> task;
    	EditText id_location;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);		
    	}
    	
    	public void startButton(View view){
    		id_location = (EditText)findViewById(R.id.editText1);
    		 task = new AsyncTaskd(this,id_location.getText().toString());
    		 task.execute(); 
    	}
    }

    AsyncTask: questo è il codice dell'AsyncTask. Si collega alla pagina php che si occupa di scrivere nel db MySQL.
    codice:
    package com.example.testscritturamysql;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.URI;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import android.content.Context;
    import android.os.AsyncTask;
    import android.widget.Toast;
    
    public class AsyncTaskd  extends AsyncTask<String,Void,String>{
    	
        String string;
        Context context;
    	  
       public AsyncTaskd(Context context, String string) {
    	   this.string = string; 
    	   this.context = context;
       }
       
       protected void onPreExecute(){
    
       }
       
       @Override
       protected String doInBackground(String... arg0) {
    	   
    	   android.os.Debug.waitForDebugger();
    	   
    	   try{
    	         String link = "http://xxxx.xxxx.xxx/access.php?type_connection=insert"+
    	         "&id_location="+string;
    	         
    	         HttpClient client = new DefaultHttpClient();
    	         HttpGet request = new HttpGet();
    	         request.setURI(new URI(link));
    	         HttpResponse response = client.execute(request);
    	         BufferedReader in = new BufferedReader
    	        (new InputStreamReader(response.getEntity().getContent()));
    	 
    	        StringBuffer sb = new StringBuffer("");
    	        String line=""; 
    	        while ((line = in.readLine()) != null) {
    	           sb.append(line);
    	           break;
    	         }
    	         in.close();
    	         return sb.toString();
    	       }catch(Exception e){
    	          return new String("Exception: " + e.getMessage());
    	       }
    	   }
       
       
       @Override
       protected void onPostExecute(String result){
    	System.out.println("Insert "+ result );
    	Toast toast = Toast.makeText(context, result, Toast.LENGTH_SHORT);
    	toast.show();
    	this.cancel(true); 
       }
    }
    Al primo inserimento va tutto bene, quando inserisco il secondo -cioè clicco il bottone per la seconda volta- inizio ad avere inserimenti multipli, sia del nuovo dato che del vecchio. Il debug mi traccia solo l'inserimento attuale che sto cercando di fare. Quello vecchio non lo vede.

  5. #4
    Androidiano L'avatar di iClaude76


    Registrato dal
    Oct 2012
    Località
    Trento
    Messaggi
    207
    Smartphone
    Galaxy S3, Nexus 7, G. Tab 2 7

    Ringraziamenti
    1
    Ringraziato 27 volte in 25 Posts
    Predefinito

    Quote Originariamente inviato da AnderAndroid Visualizza il messaggio
    Purtroppo ho provato a controllare ma i dati scritti sono corretti, ma per qualche strano motivo al secondo click sul bottone rigirano anche AsyncTask vecchi e che ormai dovrebbero essere stati rilasciati.

    Provo ad allegare un esempio di codice funzionante che soffre di questa cosa:

    Main Activity: Ha giusto un bottone ed un form da compilare. Quando si pigia il bottone quello che è scritto nel form viene messo sul db attraverso l'AsyncTask.
    codice:
    package com.example.testscritturamysql;
    
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.View;
    import android.widget.EditText;
     
    public class MainActivity extends Activity {
    	  
    	AsyncTask<String, Void, String> task;
    	EditText id_location;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);		
    	}
    	
    	public void startButton(View view){
    		id_location = (EditText)findViewById(R.id.editText1);
    		 task = new AsyncTaskd(this,id_location.getText().toString());
    		 task.execute(); 
    	}
    }

    AsyncTask: questo è il codice dell'AsyncTask. Si collega alla pagina php che si occupa di scrivere nel db MySQL.
    codice:
    package com.example.testscritturamysql;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.URI;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import android.content.Context;
    import android.os.AsyncTask;
    import android.widget.Toast;
    
    public class AsyncTaskd  extends AsyncTask<String,Void,String>{
    	
        String string;
        Context context;
    	  
       public AsyncTaskd(Context context, String string) {
    	   this.string = string; 
    	   this.context = context;
       }
       
       protected void onPreExecute(){
    
       }
       
       @Override
       protected String doInBackground(String... arg0) {
    	   
    	   android.os.Debug.waitForDebugger();
    	   
    	   try{
    	         String link = "http://xxxx.xxxx.xxx/access.php?type_connection=insert"+
    	         "&id_location="+string;
    	         
    	         HttpClient client = new DefaultHttpClient();
    	         HttpGet request = new HttpGet();
    	         request.setURI(new URI(link));
    	         HttpResponse response = client.execute(request);
    	         BufferedReader in = new BufferedReader
    	        (new InputStreamReader(response.getEntity().getContent()));
    	 
    	        StringBuffer sb = new StringBuffer("");
    	        String line=""; 
    	        while ((line = in.readLine()) != null) {
    	           sb.append(line);
    	           break;
    	         }
    	         in.close();
    	         return sb.toString();
    	       }catch(Exception e){
    	          return new String("Exception: " + e.getMessage());
    	       }
    	   }
       
       
       @Override
       protected void onPostExecute(String result){
    	System.out.println("Insert "+ result );
    	Toast toast = Toast.makeText(context, result, Toast.LENGTH_SHORT);
    	toast.show();
    	this.cancel(true); 
       }
    }
    Al primo inserimento va tutto bene, quando inserisco il secondo -cioè clicco il bottone per la seconda volta- inizio ad avere inserimenti multipli, sia del nuovo dato che del vecchio. Il debug mi traccia solo l'inserimento attuale che sto cercando di fare. Quello vecchio non lo vede.
    Quante volte vengono visualizzati i Toast?
    All' interno di doInBackground metti un Log e verifica il valore di String la prima volta e la seconda...

  6. #5
    Senior Droid


    Registrato dal
    Aug 2011
    Località
    Roma
    Messaggi
    406
    Smartphone
    Nexus 5

    Ringraziamenti
    6
    Ringraziato 32 volte in 29 Posts
    Predefinito

    Il codice che hai postato non è sufficiente a mio avviso per capire dov'è l'errore. Dovresti mettere il codice completo di padre e figlio, magari ti possiamo essere piu di aiuto

  7. #6
    Baby Droid


    Registrato dal
    Jan 2011
    Messaggi
    22

    Ringraziamenti
    2
    Ringraziato 0 volte in 0 Posts
    Predefinito

    @gioz: Quello che ho postato è il codice completo. Per semplicità ho isolato il problema abbandonando il PADRE e riportando solamente il codice del FIGLIO con relativo AsyncTask. Provo ad allegare l'intero progetto funzionante e che mi crea la duplicazione. Al primo salvataggio dell'form non ho problema, ma dal secondo in avanti sì. TestScritturaMySQL.zip

    @iClaude76: ho provato a fare come mi suggerisci ma -come già mi succedeva- al primo giro il log mi stampa il valore che sto inserendo nel DB, al secondo giro mi stampa solo il nuovo valore che sto per inserire, e non il duplicato del primo giro che viene re-inserito.

    Lato php ho verificato che l'url d'inserimento al db funzioni bene, ed infatti è così: non duplica i valori e li inserisce.

    Ho notato che debuggando il programma vengono inizializzati diversi thread di tipo AsyncTask.. a caso uno di questi viene scelto per eseguire il mio doInBackGround() quando schiaccio il bottone "save" durante il debug del progetto. Se si mettono in pausa questi thread e se ne lascia uno solo in esecuzione-mentre sto immettendo il secondo valore nel DB al secondo giro-, in un solo caso, son riuscito a forzare e a vedere anche il debug del thread fantasma che mi replica il vecchio dato.

    Grazie per l'aiuto
    Ultima modifica di AnderAndroid; 09-07-14 alle 22:33

Tag per questa discussione

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire risposte
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Torna su
Privacy Policy