Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Android] AsyncTask

Chargement d'une galerie photo

Sujet résolu
    1 août 2012 à 15:03:39

    Bonjour,

    Je suis en train de développer un module qui permet l'affichage d'une galerie photo dans mon application, celle-ci doit récupérer une liste d'url depuis une bdd, puis les afficher. J'en suis pour l'instant ici :

    MyGallery gallery;
    	
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	setContentView(R.layout.gallery);
    	gallery = (MyGallery) findViewById(R.id.gallery);
    	new LoadApplication(this).execute();
    }
    	
    private class LoadApplication extends AsyncTask<Void, Void, GalleryAdapter>{
    	Context context;
    	GalleryAdapter adapter;
    	
    	public LoadApplication(Context context) {
    		this.context = context;
    	}
    		
    	@Override
    	protected GalleryAdapter doInBackground(Void... params) {
    		String[] mURLS = getUrlPictures();
    		adapter = new GalleryAdapter(context, mURLS);
    		return adapter;
    	}
    		
    	protected void onPostExecute(GalleryAdapter adapter) {
    		gallery.setAdapter(adapter);
    	}
    }
    


    Le problème, c'est que lorsque la galerie doit s'afficher, rien ne se passe, pas de fermeture, pas de log d'erreur, pourtant la liste d'url est bien chargée. J'ai essayé de tourner ça un peu dans tout les sens sans rien trouver :o

    Donc voila, j'espère que c'est à peu près clair (Sinon vous demandez ^^ ), merci d'avance!

    Akna
    • Partager sur Facebook
    • Partager sur Twitter
      1 août 2012 à 16:00:33

      Bonjour,

      Essaye d'utiliser adapter.notifyDataSetChanged(); afin de notifier l'Adapter que le contenu du DataSet a changé et qu'il doit donc mettre à jour la View à laquelle il est rattaché.
      • Partager sur Facebook
      • Partager sur Twitter
        1 août 2012 à 16:03:42

        Merci de m'aider :)

        Alors oui j'ai déjà essayé, dans le onPostExecute et non ça ne fonctionne pas.

        Par contre je viens de remarquer qu'il y a un message dans le LogCat,
        MemoryCache MemoryCache will use up to 12.0MB
        C'est quoi exactement ?
        • Partager sur Facebook
        • Partager sur Twitter
          3 août 2012 à 22:07:05

          Bonsoir,

          A mon avis, tu sembles télécharger un peu trop d'images volumineuses pour ton application. N'oublie pas que tu programmes sur mobile et que charger plein d'image de grandes qualités n'est pas une bonne idée.

          Tu pourrais nous donner l'erreur complète ?
          • Partager sur Facebook
          • Partager sur Twitter
          Si vous voulez me retrouver, rendez-vous sur ZesteDeSavoir.
            6 août 2012 à 12:24:39

            Bonjour AndroWiiid,

            Alors je ne pense pas que cela vienne du volume de données, car lorsque je renseigne les urls manuellement, cela marche.
            (Dans le code ci-dessous, je teste avec des images HD, mais en production, je ne devrais pas gérer des images de plus de 300ko)

            MyGallery gallery;
            
            @Override
            public void onCreate(Bundle savedInstanceState) {
            	super.onCreate(savedInstanceState);
            	setContentView(R.layout.gallery);
            	gallery = (MyGallery) findViewById(R.id.gallery);
            	String[] urls = {
            		"http://static.myopera.com/community/graphics/speeddials/Opera-Background-Blue-Swirls.jpg",
            		"http://imgs.mi9.com/uploads/fine-art/4116/vector-flower-patterns-background-6011_1920x1200_70560.jpg",
            		"http://stockimagefree.com/wp-content/uploads/2012/05/abstract-blue-backgrounds-x.jpg",
            		"http://www.hdwallpapers.in/download/colorful_background-1920x1200.jpg",
            		"http://www.free-desktop-backgrounds.net/free-desktop-wallpapers-backgrounds/free-hd-desktop-wallpapers-backgrounds/40288494.jpg"
            	};
            	adapter = new GalleryAdapter(this, urls);
            	adapter.notifyDataSetChanged();
            	gallery.setAdapter(adapter);
            }
            


            Et je ne télécharge pas toutes les images en même temps, je les charges uniquement lorsque l'utilisateur va dessus.

            Image utilisateur

            Et le problème, c'est que justement, j'ai aucun message d'erreur o_O
            • Partager sur Facebook
            • Partager sur Twitter
              6 août 2012 à 12:30:08

              Bonjour,

              Cette ligne ne sert à rien : adapter.notifyDataSetChanged();. Il est inutile de notifier l'adaptateur de changements lorsque tu ne l'as pas encore attaché à ton GridView (je suppose). Ton problème est donc que rien ne s'affiche ? Es-tu certain qu'il termine de télécharger tes images en HD ? Ca peut prendre du temps.
              • Partager sur Facebook
              • Partager sur Twitter
              Si vous voulez me retrouver, rendez-vous sur ZesteDeSavoir.
                6 août 2012 à 17:29:55

                AndroWiiid, merci de m'aider :)

                Donc en fait, le code dans mon premier post est celui que je voudrais faire marcher, et celui dans mon dernier post est juste un code de test.

                Mon code de test marche parfaitement bien, les images s'affichent correctement et je n'ai aucun soucis de téléchargement (HD ou non, et même avec un très grand nombre d'images). Mais le problème c'est que les url des images sont renseignées manuellement, hors je voudrais que cela soit dynamique.

                Dans le code que je veux faire marcher, je récupère donc la liste d'url dynamiquement depuis une BDD, mais lorsque je fais mon setAdatpter(), rien ne se passe (Et l'adapter n'est pas vide puisqu'il contient bien le nombre d'objets que je souhaite charger)
                • Partager sur Facebook
                • Partager sur Twitter
                  6 août 2012 à 18:25:16

                  Si ton adaptateur possède des items, c'est bizarre. Puis-je voir comment tu l'as implémenté ?
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Si vous voulez me retrouver, rendez-vous sur ZesteDeSavoir.
                    7 août 2012 à 8:52:28

                    Pour mon adapter :

                    public class GalleryAdapter extends BaseAdapter {
                        
                        private Context context;
                        private String[] data;
                        private static LayoutInflater inflater=null;
                        public ImageLoader imageLoader;
                    
                        public GalleryAdapter(Context c, String[] d) {
                            context = c;
                            data=d;
                            inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                            imageLoader=new ImageLoader(context);
                        }
                    
                        public int getCount() {
                            return data.length;
                        }
                    
                        public Object getItem(int position) {
                        	return data[position];
                        }
                    
                        public long getItemId(int position) {
                            return position;
                        }
                    
                        public View getView(int position, View convertView, ViewGroup parent) {
                            View vi=convertView;
                            if(convertView==null) vi = inflater.inflate(R.layout.gallery_item, parent, false);
                            ImageView image= (ImageView) vi.findViewById(R.id.image);
                            ProgressBar progress = (ProgressBar) vi.findViewById(R.id.image_progress);
                            imageLoader.DisplayImage(data[position], image, progress);
                            return vi;
                        }
                    }
                    
                    • Partager sur Facebook
                    • Partager sur Twitter
                      7 août 2012 à 9:39:59

                      Oki, ton adaptateur semble correct (je vois que tu as copier/coller un tuto sur le net sur le chargement d'image ^^ ). C'est alors peut-être l'ordre de tes executions qui posent problème. Essaye plutôt quelque chose comme :

                      private MyGallery mGallery;
                      private GalleryAdapter mAdapter;
                      private String[] mItems;
                      	
                      @Override
                      public void onCreate(Bundle savedInstanceState) {
                      	super.onCreate(savedInstanceState);
                      	setContentView(R.layout.gallery);
                      
                      	// Initialise la galerie
                      	this.mGallery = (MyGallery) findViewById(R.id.gallery);
                      	this.mAdapter = new GalleryAdapter(context, mURLS);
                      	this.mGallery.setAdapter(this.mAdapter);
                      
                      	// Lance le thread asynchrone
                      	new LoadApplication().execute();
                      }
                      	
                      private class LoadApplication extends AsyncTask<Void, Void, Void>{
                      		
                      	@Override
                      	protected void doInBackground(Void... params) {
                      		this.mItems = getUrlPictures();
                      		return null;
                      	}
                      		
                      	protected void onPostExecute(GalleryAdapter adapter) {
                      		this.mGallery.addAll(this.mItems);
                      		this.mAdapter.notifyDataSetChanged();
                      	}
                      }
                      


                      Quant à ton adaptateur :

                      public class GalleryAdapter extends BaseAdapter {
                          
                          private Context context;
                          private String[] data;
                          private static LayoutInflater inflater=null;
                          public ImageLoader imageLoader;
                      
                          public GalleryAdapter(Context c, String[] d) {
                              context = c;
                              data=d;
                              inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                              imageLoader=new ImageLoader(context);
                          }
                      
                          public int getCount() {
                              return data.length;
                          }
                      
                          public Object getItem(int position) {
                          	return data[position];
                          }
                      
                          public long getItemId(int position) {
                              return position;
                          }
                      
                          public View getView(int position, View convertView, ViewGroup parent) {
                              View vi=convertView;
                              if(convertView==null) vi = inflater.inflate(R.layout.gallery_item, parent, false);
                              ImageView image= (ImageView) vi.findViewById(R.id.image);
                              ProgressBar progress = (ProgressBar) vi.findViewById(R.id.image_progress);
                              imageLoader.DisplayImage(data[position], image, progress);
                              return vi;
                          }
                      
                      	public void addAll(String[] data) {
                      		this.data = data;
                      	}
                      }
                      


                      Ce code devrait marcher normalement. Je trouvais bizarre que tu fasses autant de chose dans un thread secondaire.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Si vous voulez me retrouver, rendez-vous sur ZesteDeSavoir.
                        7 août 2012 à 10:46:42

                        Oui j'ai récupéré le image loader sur un tuto (Celui là je crois) et l'adapter un peu à ma sauce pour qu'il corresponde à une galerie ^^

                        Donc j'ai tenté ça (j'ai dû adapter un peu le code) :

                        private MyGallery mGallery;
                        private GalleryAdapter mAdapter;
                        private String[] mItems;
                        	
                        @Override
                        public void onCreate(Bundle savedInstanceState) {
                        	super.onCreate(savedInstanceState);
                        	setContentView(R.layout.gallery);
                        
                        	// Initialise la galerie
                        	this.mGallery = (MyGallery) findViewById(R.id.gallery);
                        	this.mAdapter = new GalleryAdapter(this, mItems);
                        	this.mGallery.setAdapter(this.mAdapter);
                        
                        	// Lance le thread asynchrone
                        	new LoadApplication().execute();
                        }
                        	
                        private class LoadApplication extends AsyncTask<Void, Void, Void>{
                        		
                        	@Override
                        	protected Void doInBackground(Void... params) {
                        		mItems = getUrlPictures();
                        		return null;
                        	}
                        		
                        	protected void onPostExecute(Void test) {
                        		mAdapter.addAll(mItems);
                        		mAdapter.notifyDataSetChanged();
                        	}
                        }
                        


                        Mais maintenant j'ai un force close de l'appli, et apparemment c'est la ligne 13, au setAdapter(), qui fait planter :(
                        • Partager sur Facebook
                        • Partager sur Twitter
                          7 août 2012 à 21:45:18

                          Tu pourrais donner l'erreur du LogCat ?
                          • Partager sur Facebook
                          • Partager sur Twitter
                          Si vous voulez me retrouver, rendez-vous sur ZesteDeSavoir.
                            8 août 2012 à 9:15:39

                            Ok, je sais pourquoi. En fait, puisque tu alimentes ton tableau de données dans ton adaptateur par après (lorsque la requête asynchrone est terminée), du côté de l'adaptateur il possède un tableau non initialisé.

                            Il suffit, dans le constructeur de l'adaptateur, d'initialiser à vide ton tableau de données.
                            • Partager sur Facebook
                            • Partager sur Twitter
                            Si vous voulez me retrouver, rendez-vous sur ZesteDeSavoir.
                              8 août 2012 à 9:37:45

                              Donc du coup j'ai ça dans mon adapter :
                              private String[] data = null;
                              

                              Mais j'ai toujours la même erreur, et lorsque j'enlève la ligne
                              this.mGallery.setAdapter(this.mAdapter);
                              

                              je n'ai plus d'erreur (Bon du coup il s'affiche rien mais bon ^^ )
                              • Partager sur Facebook
                              • Partager sur Twitter
                                8 août 2012 à 9:39:43

                                Non, là tu initialises pas à vide. Tu dois initialiser comme ceci :
                                private String[] data = new String[TAILLE];
                                
                                • Partager sur Facebook
                                • Partager sur Twitter
                                Si vous voulez me retrouver, rendez-vous sur ZesteDeSavoir.
                                  20 août 2012 à 10:29:59

                                  Bonjour,
                                  Tout d'abord désolé pour le retard, j'ai du abandonner ce projet pendant un moment :colere2:

                                  Donc j'ai bien fais les modifications que tu m'as conseillé, et ça marche presque !!!!
                                  Il y a juste quand je vais sur la galerie, la première image ne s'affiche pas et l'appli affiche le loader qui tourne en boucle. Par contre si je change d'image, tout fonctionne impec ! (Même quand je reviens sur la première image elle se charge !)
                                  Donc en gros ça coince juste à l'ouverture de la galerie, une fois que ce problème est réglé, ça va être top :)

                                  J'ai pas trop le temps de regarder en ce moment, mais dès que je peux je remet le nez dedans !
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    21 août 2012 à 12:04:43

                                    Il ne te donne aucun message d'erreur ?
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Si vous voulez me retrouver, rendez-vous sur ZesteDeSavoir.
                                      22 août 2012 à 9:28:26

                                      Bonjour AndroWiiid,
                                      Non j'ai aucun message d'erreur, en fait je pense que c'est mon adapter qui se rafraîchit pas une fois que la liste d'url est envoyé, du coup il reste vide.
                                      Le mAdapter.notifyDataSetChanged(); est censé corriger ça normalement non ?
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        27 août 2012 à 15:50:54

                                        Voila je peux enfin me repencher sur ce problème, et je comprend vraiment pas pour le coup.
                                        J'en suis pour le moment à ce point :

                                        private MyGallery mGallery;
                                        private GalleryAdapter mAdapter;
                                        private String[] mItems = new String[1];
                                        	
                                        @Override
                                        public void onCreate(Bundle savedInstanceState) {
                                        	super.onCreate(savedInstanceState);
                                        	setContentView(R.layout.gallery);
                                        
                                        	this.mGallery = (MyGallery) findViewById(R.id.gallery);
                                        	this.mAdapter = new GalleryAdapter(this, mItems);
                                        	this.mGallery.setAdapter(this.mAdapter);
                                        
                                        	new LoadApplication().execute();
                                        }
                                        
                                        private class LoadApplication extends AsyncTask<Void, Void, Void>{
                                        	@Override
                                        	protected Void doInBackground(Void... params) {
                                        		mItems = getUrlPictures();
                                        		mAdapter.addAll(mItems);
                                        		return null;
                                        	}
                                        		
                                        	protected void onPostExecute(Void test) {
                                        		mAdapter.notifyDataSetChanged();
                                            		System.out.println(mGallery.getItemAtPosition(0));
                                            		//Retourne l'url de la première photo qui doit être chargée.
                                        	}
                                        }
                                        


                                        Et le println à la fin me donne bien l'url de la première photo qui est envoyées, mais elle ne s'affiche pas :colere2:
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          28 août 2012 à 12:31:53

                                          dans onPostExecute

                                          essaie de rajouter cette ligne :

                                          mGallery.setAdapter(this.mAdapter);

                                          pour voir ce que ça donne.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            28 août 2012 à 14:19:51

                                            Bonjour Epoch,

                                            Non j'ai déjà essayé, dans ce cas là, rien ne se passe, je ne peux même pas afficher une seule image.
                                            Ce qui est bizarre, c'est que le mAdapter.notifyDataSetChanged(); devrait refresh l'adapter je crois, et là j'ai l'impression qu'il ne fait rien du tout.

                                            EDIT :
                                            Oula, alors j'ai réussi à le faire fonctionner finalement :D Par contre je suis absolument pas sûr que le code soit très propre...

                                            private MyGallery mGallery;
                                            private GalleryAdapter mAdapter;
                                            private String[] mItems = new String[1];
                                            	
                                            @Override
                                            public void onCreate(Bundle savedInstanceState) {
                                            	super.onCreate(savedInstanceState);
                                            	setContentView(R.layout.gallery);
                                            
                                            	this.mGallery = (MyGallery) findViewById(R.id.gallery);
                                            	this.mAdapter = new GalleryAdapter(this, mItems);
                                            	this.mGallery.setAdapter(this.mAdapter);
                                            
                                            	new LoadApplication().execute();
                                            }
                                            
                                            private class LoadApplication extends AsyncTask<Void, Void, Void>{
                                            	@Override
                                            	protected Void doInBackground(Void... params) {
                                            		mItems = getUrlPictures();
                                            		mAdapter.addAll(mItems);
                                            		return null;
                                            	}
                                            		
                                            	protected void onPostExecute(Void test) {
                                            		mAdapter.notifyDataSetChanged();
                                            		mGallery.onLayout(true,0,0,0,0);
                                            	}
                                            }
                                            


                                            J'ai juste rajouté mGallery.onLayout(true,0,0,0,0); et comme par magie cela marche o_O
                                            Bon pour l'instant je laisse comme ça, mais si vous avez des suggestions je suis toujours preneur!
                                            En tout cas merci de vos réponses !
                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            [Android] AsyncTask

                                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                            • Editeur
                                            • Markdown