IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

AutoCompleteTextView & onItemClick


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2012
    Messages : 535
    Par défaut AutoCompleteTextView & onItemClick
    Salut!

    Un truc totalement surréaliste (au moins pour moi!) me faisant tourner en bourrique!

    Contexte:
    -> un champ AutoCompleteTextView ville
    -> utilisant une List:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    List<String> listeAffichageVille = new ArrayList<String>();
    -> elle même initialisée dans onTextChanged par une requête Php dans un thread (à cause des accès réseaux)
    -> à partir du 4ème caractère saisi, le champ ville propose des items de listeAffichage
    -> onItemClick récupère l'item de la position clickée
    Ok.....

    Là ou ça se corse:
    1er point, déjà louche: le thread de remplissage de la liste est relancé par le onItemClick une fois de plus(???)

    et ensuite, son comportement n'est pas identique, il ramène de 1 à n lignes, alors qu'on ne clique que sur une seule ligne des propositions faites!

    C'est vraiment compliqué à expliquer, et je ne sais pas si je suis clair, alors essayons des exemples:

    ex1:
    -> je tape MARS, ville me propose donc des villes connues de Php débutant par MARS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    12-11 11:11:06.850: E/Thread-----------> 0(6257): Mars (Ardèche, Rhône-Alpes)
    12-11 11:11:06.850: E/Thread-----------> 1(6257): Mars (Dordogne, Aquitaine)
    12-11 11:11:06.850: E/Thread-----------> 2(6257): Mars (Gard, Languedoc-Roussillon)
    12-11 11:11:06.850: E/Thread-----------> 3(6257): Mars (Loire, Rhône-Alpes)
    12-11 11:11:06.850: E/Thread-----------> 4(6257): Marsa (Aude, Languedoc-Roussillon)
    12-11 11:11:06.850: E/Thread-----------> 5(6257): Marsac (Charente, Poitou-Charentes)
    12-11 11:11:06.850: E/Thread-----------> 6(6257): Marsac (Creuse, Limousin)
    12-11 11:11:06.850: E/Thread-----------> 7(6257): Marsac (Gironde, Aquitaine)
    12-11 11:11:06.850: E/Thread-----------> 8(6257): Marsac (Hautes-Pyrénées, Midi-Pyrénées)
    12-11 11:11:06.850: E/Thread-----------> 9(6257): Marsac (Tarn-et-Garonne, Midi-Pyrénées)
    12-11 11:11:06.850: E/Thread-----------> 10(6257): Marsal (Dordogne, Aquitaine)
    12-11 11:11:06.850: E/Thread-----------> 11(6257): Marsal (Moselle, Lorraine)
    12-11 11:11:06.850: E/Thread-----------> 12(6257): Marsal (Tarn, Midi-Pyrénées)
    12-11 11:11:06.850: E/Thread-----------> 13(6257): Marsal (Rhône-Alpes)
    12-11 11:11:06.850: E/Thread-----------> 14(6257): Marsan (Creuse, Limousin)
    12-11 11:11:06.850: E/Thread-----------> 15(6257): Marsan (Gers, Midi-Pyrénées)
    12-11 11:11:06.850: E/Thread-----------> 16(6257): Marsan (Loiret, Centre)
    12-11 11:11:06.850: E/Thread-----------> 17(6257): Marsan (Rhône-Alpes)
    12-11 11:11:06.850: E/Thread-----------> 18(6257): Marsas (Gironde, Aquitaine)
    12-11 11:11:06.850: E/Thread-----------> 19(6257): Marsas (Hautes-Pyrénées, Midi-Pyrénées)
    -> je sélectionne "Mars (Gard)", le thread est relancé et ramène
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    12-11 11:11:11.410: E/Thread-----------> 0(6257): Mars (Ardèche, Rhône-Alpes)
    12-11 11:11:11.410: E/Thread-----------> 1(6257): Mars (Dordogne, Aquitaine)
    12-11 11:11:11.410: E/Thread-----------> 2(6257): Mars (Gard, Languedoc-Roussillon)
    12-11 11:11:11.410: E/Thread-----------> 3(6257): Mars (Loire, Rhône-Alpes)
    DONC 4 lignes...

    ex2: (toujours le même code source of course!)
    -> je tape MULH, ville me propose donc des villes connues de Php débutant par MULH
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    12-11 11:11:26.930: E/Thread-----------> 0(6257): Mulheim (Province de Limbourg)
    12-11 11:11:26.930: E/Thread-----------> 1(6257): Mulhouse (Haut-Rhin, Alsace)
    12-11 11:11:26.930: E/Thread-----------> 2(6257): Mulhausen (Bas-Rhin, Alsace)
    -> je sélectionne "Mulhouse (Haut Rhin), le thread est relancé et ramène
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    12-11 11:11:28.340: E/Thread-----------> 0(6257): Mulhouse (Haut-Rhin, Alsace)
    DONC 1 ligne........

    ex3: (toujours le même code source of course!)
    -> je tape PERR, ville me propose donc des villes connues de Php débutant par PERR
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    12-11 11:34:01.310: E/Thread-----------> 0(6825): Perre (Indre-et-Loire, Centre)
    12-11 11:34:01.310: E/Thread-----------> 1(6825): Perre (Flandre Orientale)
    12-11 11:34:01.310: E/Thread-----------> 2(6825): Perran (Bretagne)
    12-11 11:34:01.310: E/Thread-----------> 3(6825): Perray (Indre-et-Loire, Centre)
    12-11 11:34:01.310: E/Thread-----------> 4(6825): Perret (Côtes-d'Armor, Bretagne)
    12-11 11:34:01.310: E/Thread-----------> 5(6825): Perret (Rhône-Alpes)
    12-11 11:34:01.310: E/Thread-----------> 6(6825): Perrex (Ain, Rhône-Alpes)
    12-11 11:34:01.310: E/Thread-----------> 7(6825): Perros (Finistère, Bretagne)
    12-11 11:34:01.310: E/Thread-----------> 8(6825): Perros (Finistère, Bretagne)
    12-11 11:34:01.310: E/Thread-----------> 9(6825): Perros (Bretagne)
    12-11 11:34:01.310: E/Thread-----------> 10(6825): Perrou (Orne, Basse-Normandie)
    12-11 11:34:01.310: E/Thread-----------> 11(6825): Perroy (Nièvre, Bourgogne)
    12-11 11:34:01.310: E/Thread-----------> 12(6825): Perroy ()
    12-11 11:34:01.310: E/Thread-----------> 13(6825): Perreux (Loire, Rhône-Alpes)
    12-11 11:34:01.310: E/Thread-----------> 14(6825): Perreux (Yonne, Bourgogne)
    12-11 11:34:01.310: E/Thread-----------> 15(6825): Perrier (Dordogne, Aquitaine)
    12-11 11:34:01.310: E/Thread-----------> 16(6825): Perrier (Puy-de-Dôme, Auvergne)
    12-11 11:34:01.310: E/Thread-----------> 17(6825): Perruel (Eure, Haute-Normandie)
    12-11 11:34:01.310: E/Thread-----------> 18(6825): Perrelli (Corse)
    12-11 11:34:01.310: E/Thread-----------> 19(6825): Perreuil (Saône-et-Loire, Bourgogne)
    -> je sélectionne "Perret (Côtes-d'Armor)" (le 5ème de la liste, indice 4 donc), le thread est relancé et ramène
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    12-11 11:34:26.750: E/Thread-----------> 0(6825): Perret (Côtes-d'Armor, Bretagne)
    12-11 11:34:26.750: E/Thread-----------> 1(6825): Perret (Rhône-Alpes)
    DONC 2 lignes cette fois-ci........
    -> et BOUM!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    java.lang.IndexOutOfBoundsException: Invalid index 4, size is 2
    puisque l'indice récupéré par onItemClick est le bon, 4 ici.... mais comme le thread est relancé au moment du onItemClick et qu'il ne ramène que 2 lignes, on est hors index!


    Pourquoi ça me gène
    -> d'abord parce que je ne trouve pas ce comportement normal
    -> et ensuite, surtout parce que parfois, la position ramenée par onItemClick n'est pas la bonne, et donc crache l'appli (java.lang.IndexOutOfBoundsException) pour un mauvais index.
    -> le tout étant "aléatoire" puisque durant mon dev je testais avec 1 ou 2 villes, toujours les mêmes, et RAS
    -> là j'arrive au bout, donc je teste un peu plus "intensément".... et c'est là que je me rend compte du problème....

    Ai-je réussi à me faire comprendre par ces exemples?

    Une idée peut être?
    Qu'est ce qui m'échappe?

    Merci.

  2. #2
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2012
    Messages : 535
    Par défaut
    PRECISION:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public void onItemClick(AdapterView<?> parent, View arg1, int position, long id) 
    {
    idClickedVille = a_idVil.get(position);
    }
    avec la globale
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    private ArrayList<String> a_idVil = new ArrayList<String>();
    qui stocke en // les ID des villes de la liste... et c'est cet ID que je dois récupérer

  3. #3
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Je ne vois rien d'aléatoire, il récupère systématiquement les villes qui commencent par le texte entré jusqu'au premier espace...

    Maintenant, on a comment cela se passe.... il faudrait voir comment c'est fait ^^ un peu de code (le thread de remplissage, le 'onItemClick', le onTextChanged et surtout la requête en base de donnée).

    D'autre part, tu parles très souvent "d'index", c'est une valeur facétieuse en informatique les index Il vaut mieux conserver des références uniques qu'un truc qui change à chaque insert (comme tu le dis l'index change, et en plus de manière asynchrone avec un thread, donc on ne sait pas trop quand).

    Je ne sais pas si tu as un identifiant unique... mais par exemple conserver un truc genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    class VilleReference
    {
        long    id;
        String display;
     
        public long getId() { return this.id; }
        public String getDisplay() { return this.display; }
        public void setId(long i) { this.id = i; }
        public void setDisplay(String t) { this.display = t; }
     
        public String toString() { return this.display; }
    }
    Et dès qu'on recoit un click, conserver CETTE référence là (on a tout, l'ID en BDD, et le texte) éviterait déjà des conversions d'index perilleuses lors de changements de la liste.
    Bien sur si il n'y a pas d'identifiant 'numérique' en base de donnée, c'est la chaine complète qu'il faut stocker...

  4. #4
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2012
    Messages : 535
    Par défaut
    Le problème serait donc l'espace?
    -> dans ce cas on aurait le même plantage pour BORD & MARS

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
    private Integer errorMsgId;
    private String  errorMsgParam;
    private List<String> listeAffichageVille = new ArrayList<String>();
    private ArrayList<String> a_idVil = new ArrayList<String>();
    private int villePosition = -1;
    private String idClickedVille = "";
     
    public void onTextChanged(CharSequence s, int start, int before, int count) 
    {    	
    	if (ville.enoughToFilter())		//REQUETE uniquement à partir de 'n' caractères saisis (threshold = 4 ici dans .XML)!
        	{    		
    	    	builtURL = CONFIG_UNIQ_ID + separateur + String.valueOf(VILLE + separateur + ville.getText());
    	    	RemplirVille2 thread;
    			try 
    			{
    				thread = new RemplirVille2(BASE_URL4 + URLEncoder.encode(Fonctions.cryptage3DES(builtURL),"UTF-8"));
    				thread.start();
    			    while (thread.isAlive())
    			    {
    			    	//rien, juste attendre fin thread pour envoyer la liste à l'adapter
    			    	SystemClock.sleep(1);		    	
    			    }
    			} 
    			catch (UnsupportedEncodingException e) 
    			{
    				e.printStackTrace();
    			}
     
    		    //bloc équivalent au onPostExecute d'Async
    		    //****************************************
    		    if (listeAffichageVille == null)	//si NULL alors problème...
    			{
    				  if (errorMsgId != null) 
    			      {
                          String msg = this.getString(this.errorMsgId);
                          Toast.makeText(this,msg,Toast.LENGTH_LONG).show();
    			      }    
    			}
    			else				//.. SINON affecter les data à l'adapter! 
    			{
    				ville.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_selectable_list_item,listeAffichageVille));
    				//DEBUG
    				int i = 0, j = 0;
    				for (String s1 : listeAffichageVille)	{ Log.e("onTextChanged-----------> " + i,s1); i++;}
    				for (String s2 : a_idVil)				{ Log.e("onTextChanged-----------> " + j,s2); j++;}				
    			}
        	}
    }
    ET
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
     
    class RemplirVille2 extends Thread
    {
        	private String URL;
        	private int return_code;
     
        	public int getValue() 				{ return return_code; }
            public RemplirVille2(String url)	{ this.URL = url; }
     
        	public void run() 
        	{
    	    	ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
     
    	    	try 
    			{
    	    		 	 HttpClient httpclient = new DefaultHttpClient();
    	    		 	 final HttpParams httpParams = httpclient.getParams();
    	    		 	 HttpConnectionParams.setConnectionTimeout(httpParams, CONFIG_TIMEOUT_RESEAU);
    	    		 	 HttpConnectionParams.setSoTimeout(httpParams, CONFIG_TIMEOUT_RESEAU);
    	    		 	 HttpPost httppost = new HttpPost(URL);
    	    		 	 httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
     
    	    		 	 HttpResponse response = httpclient.execute(httppost);
     
                         if (response.getStatusLine().getStatusCode() < 400) 
    					 {
     
                        	  HttpEntity entity = response.getEntity();
                              String encodedArray = EntityUtils.toString(entity);
                              String decodedArray = Fonctions.decryptagePassword3DES(encodedArray,CONFIG_CLE_DATA_CRYPTE);
                              JSONArray json_array = new JSONArray(decodedArray);
     
                              listeAffichageVille.clear();		//IMPORTANTISSIME!!! vider avant chaque remplissage, sinon data APPEND!!!
                              a_idVil.clear();
     
                              for(int i=0;i<json_array.length();i++) 
    						  {
                                  JSONObject json_ligne = json_array.getJSONObject(i);   
                                  listeAffichageVille.add(json_ligne.getString("VILLE"));
                                  a_idVil.add(json_ligne.getString("CLEF_VILLE"));
                                  return_code = 1;   
    						  }
     
                              //DEBUG
                              int i = 0, j = 0;
                              for (String s1 : listeAffichageVille) { Log.e("Thread-----------> " + i,listeAffichageVille.get(i)); i++; }
                              for (String s2 : a_idVil)             { Log.e("Thread-----------> " + j,a_idVil.get(j)); j++; }
    					} 
    					else 
    					{
    						Log.e("THREAD RemplirVille2: EXCEPTION http error ", "--"+response.getStatusLine().toString()+"--"); 
                            errorMsgId = R.string.http_site_error;
                            listeAffichageVille = null;
                            return_code = -1;
                        }
    	        } 
    			catch (Exception ex) 
    			{
                		Log.e("THREAD RemplirVille2: EXCEPTION decode error", "--"+ex.toString()+"--");
                        errorMsgId = R.string.http_decode_error;
                        errorMsgParam = ex.getLocalizedMessage();
                        listeAffichageVille = null;
                        return_code = -1;
                }  
        	}
    }
    PS: désolé pour les indentations pourries, mais si qq'un à une astuce pour 1 copy/paste efficace de ce point de vue là, je prends aussi!

  5. #5
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Déjà: ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    				thread = new RemplirVille2(BASE_URL4 + URLEncoder.encode(Fonctions.cryptage3DES(builtURL),"UTF-8"));
    				thread.start();
    			    while (thread.isAlive())
    			    {
    			    	//rien, juste attendre fin thread pour envoyer la liste à l'adapter
    			    	SystemClock.sleep(1);		    	
    			    }
    Pourquoi faire un thread dans ce cas ? ... Autant le faire directement ça sera plus rapide (la création d'un thread c'est long).


    Bon... il manque le 'onClick'... mais ma boule de cristal m'a montré une image.... le onClick va changer le texte, et du coup, appeler le onTextChanged() .... ce qui expliquerait pourquoi le thread (enfin ... la fonction en l’occurrence) est appelée par le onClick...

    Du "Log.i()" ou "Log.v()" de temps à autre aiderait à comprendre le déroulement exactement.
    Attention aux Log.e() aussi:
    Log.e("THREAD RemplirVille2: EXCEPTION decode error", "--"+ex.toString()+"--");
    Ne veut rien dire... le tag devrait permettre de trouver rapidement les logs concernant un bout de code (par exemple "THREAD RemplirVille2"), le message, ben c'est le message.... l'exception doit être passée en dernier paramètre !
    Donc:
    Log.e("THREAD RemplirVille2","EXCEPTION decode error",ex);


    Je reviens tout à l'heure....

  6. #6
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2012
    Messages : 535
    Par défaut
    Déjà: ca:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    				thread = new RemplirVille2(BASE_URL4 + URLEncoder.encode(Fonctions.cryptage3DES(builtURL),"UTF-8"));
    				thread.start();
    			    while (thread.isAlive())
    			    {
    			    	//rien, juste attendre fin thread pour envoyer la liste à l'adapter
    			    	SystemClock.sleep(1);		    	
    			    }
    Pourquoi faire un thread dans ce cas ? ... Autant le faire directement ça sera plus rapide (la création d'un thread c'est long).
    ben(?), simplement parce qu'on ne peut pas faire d'accès réseau dans le UI.
    -> je trouve le wait très moyen
    -> mais en attendant de trouver mieux...

    Bon... il manque le 'onClick'... mais ma boule de cristal m'a montré une
    non, je ne l'ai juste pas re-posté puisque je l'avais déjà fait avant

    image.... le onClick va changer le texte, et du coup, appeler le onTextChanged() .... ce qui expliquerait pourquoi le thread (enfin ... la fonction en l’occurrence) est appelée par le onClick...
    oui MAIS en faisant un clic, tu en sélectionnes qu'une seule ligne dans la liste..... donc pourquoi en renvoyer 4, ou 2 au lieu de simplement ramener celle que tu as choisis quoi?

    Du "Log.i()" ou "Log.v()" de temps à autre aiderait à comprendre le déroulement exactement.
    moi j'en ai, c'est comme ça que j'ai compris ce qui se passait.
    je les ai juste virés ici par soucis de clarté.

    Attention aux Log.e() aussi:
    Log.e("THREAD RemplirVille2: EXCEPTION decode error", "--"+ex.toString()+"--");
    Ne veut rien dire... le tag devrait permettre de trouver rapidement les logs concernant un bout de code (par exemple "THREAD RemplirVille2"), le message, ben c'est le message.... l'exception doit être passée en dernier paramètre !
    Donc:
    Log.e("THREAD RemplirVille2","EXCEPTION decode error",ex);
    ok


    PS:
    - la requête en base, elle, renvoie bien ce qu'il faut, c'est vérifié.
    - le plus simple serait de ne pas (re)lancer le thread sur le onClick, mais comment?
    - pkoi je gère un tableau d'ID à coté de la liste de libellés? parce que si j'inclus les ID (et je parle bien d'ID, pas d'index) aux libellés, on verra aussi les ID à l'affichage de la liste.

  7. #7
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mai 2012
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mai 2012
    Messages : 535
    Par défaut
    Bref, tout ça c'est MA solution/vision de débutant... pas forcément optimale par définition... donc si on peut faire mieux, pas de soucis, je n'ai rien contre l'apprentissage.

    Ce que je pensais que ça ferait:
    onTextChanged() --> thread --> affichage liste --> <select ville dans liste> --> onClick(), avec récupération de l'indice de la ville clickée = int position

    Ce que ça fait vraiment:
    onTextChanged() --> thread --> affichage liste --> <select ville dans liste> --> onTextChanged() --> thread --> onClick() MAIS avec la valeur int position de <select ville dans liste> (ex3 ci-dessus: 20 items) et non du 2ème passage dans thread (ex3 ci-dessus: 2 items)

  8. #8
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    ben(?), simplement parce qu'on ne peut pas faire d'accès réseau dans le UI.
    Oui, parce qu'on ne peut pas ATTENDRE dans le thread UI, que ce soit par une attente IO de réseau, ou par un simple 'sleep()' !


    Voici un 'exemple' d'implémentation, je n'ai pas vérifié si cela compilait/marchait, juste l'idée de base....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
     
    class MyActivity extends Activity implements AdapterView.OnItemClickListener
    {
        // on garde des données cohérentes... peu importe si cela complexifie certaines parties du code, les bugs disparaitront comme par magie 
        static class Ville {
            String id;
            String name;
     
            @Override
            public String toString() { return this.name; }
        };
     
     
     
        ArrayAdapter<Ville>  villeAdapter;
        String                     villeAdapterFilter;
        VilleUpdateTask        villeAdapterUpdateTask;
        AutoCompleteTextView villeText;
     
        Ville                       selectedVille;
     
     
        final TextWatcher textChecker = new TextWatcher() {
     
            public void afterTextChanged(Editable s) {}
     
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
     
            public void onTextChanged(CharSequence s, int start, int before, int count)
            { 
                  MyActivity.this.setAdapterFilter(s.toString());
            }
     
        };
     
        public void onCreate(Bundle bundle)
        {
             super.onCreate(bundle);
             setContentView(R.layout.xxxxxx);
     
             // au début, l'adapter est vide....
             this.villeAdapter = new ArrayAdapter<Ville>(this,android.R.layout.simple_dropdown_item_1line, new Ville[0]);
              // on setup le textview
             this.villeText = (AutoCompleteTextView ) findViewById(R.id.villeSelector);
             this.villeText.setAdapter(this.villeAdapter);
             this.villeText.setThreshold(THRESHOLD_DROPDOWN); 
             this.villeText.setOnItemClickListener(this);
             this.villeText.addTextChangedListener(textChecker);
        }
     
        public void onDestroy() {
             stopVilleAdapterUpdate();
        }
     
     
        public void setAdapterFilter(String filter)
        {
             if (filter == null) {
                 // clearing the adapter
                 this.villeAdapterFilter = null;
                 this.villeAdapter.clear();
                 this.villeAdapter.notifyDataSetChanged();
                 Log.d("MyActivity","Clearing ville filter !");
             } else if (filter.length() > THRESHOLD_QUERY) {
                  if (this.villeAdapterFilter == null) {
                      Log.d("MyActivity","Ville Adapter Filter defined to:"+filter);
                      this.villeAdapterFilter = filter;
                      startVilleAdapterUpdate();
                  } else {
                      Log.d("MyActivity","Already filtered with:"+this.villeAdapterFilter);
                  }
             } else {
                  Log.d("MyActivity","Resetting filter (not enough data)");
                  this.villeAdapterFilter = null;
                 this.villeAdapter.clear();
                 this.villeAdapter.notifyDataSetChanged();
             }
        }
     
        public synchronized void onItemClick(ViewAdapter<?> ad, View v, int position, long id)
        {
             this.selectedVille = this.villeAdapter.getItemAtPosition(position);
             Log.d("MyActivity","Ville selected: "+this.selectedVille);
        }
     
        public synchronized void startVilleAdapterUpdate()
        {
              stopVilleAdapterUpdate();
              Log.d("MyActivity","Starting Update of Villes with "+this.villeAdapterFilter);
              this.villeAdapterUpdateTask = new VilleUpdateTask();
              this.villeAdapterUpdateTask.execute(this.villeAdapterFilter);
        }
     
        public synchronized void stopVilleAdapterUpdate()
        {
             if (this.villeAdapterUpdateTask != null) {
                 Log.d("MyActivity","Stopping current update of villes");
                 this.villeAdapterUpdateTask.cancel(true);
                 this.villeAdapterUpdateTask = null;
             }
        }
     
        public synchronized void onVilleAdapterUpdateResult(Ville[] data)
        {
             this.villeAdapterUpdateTask = null;
             if (data != null) {
                 Log.d("MyActivity","Received "+data.length+" villes from update task");
                 this.villeAdapter.clear();
                 this.villeAdapter.addAll(data);
                 this.villeAdapter.notifyDataSetChanged(); // mise à jour du drop down...
            }
        } 
     
        class VilleUpdateTask extends AsyncTask<String,Void,Ville[]>
        {
              public Ville[] doInBackground(String ... filters)
              {
                  ArrayList<Ville> values = new ArrayList<Ville>();
                  try  {
                       HttpClient httpclient = new DefaultHttpClient();
                       ....
                       ....
                       for(int i=0;i<json_array.length();i++) {
                           JSONObject json_ligne = json_array.getJSONObject(i);   
                           try {
                               Ville v = new Ville();
                               v.name = json_ligne.getString("VILLE");
                               v.id = json_ligne.getString("CLEF_VILLE");
                               values.add(v);
                           } catch (Exception ex) {
                               Log.w("VilleUpdateTask","Invalid value for Ville at index #"+i,ex);
                           }
                       }
                  } catch (Exception ex) {
                       Log.e("VilleUpdateTask","Failed to retrieve list of Ville !",ex);
                  }
                  return values.toArray(new Ville[values.size()]);
             }
     
             public void onPostExecute(Ville[] data)
             {
                 MyActivity.this.onVilleAdapterUpdateResult(data);
             }
        }
     
    }
    EDIT: L'auto-complete va déjà limiter l'affichage à ce qui correspond de l'adapter.... Donc une fois qu'il est rempli, à priori, sauf si on supprime des caractères (en deçà du "threshold", pas besoin de refaire de requête). Du coup j'ai corrigé les fonctions....

+ Répondre à la discussion
Cette discussion est résolue.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo