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 :

Architecture des applications Android


Sujet :

Android

  1. #1
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2014
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2014
    Messages : 40
    Par défaut Architecture des applications Android
    Bonjour à tous,

    Je suis donc un débutant niveau 2, c'est à dire que j'arrive à faire un certains nombres de choses relativement basique mais dès ma première application je me retrouve confronté à la possibilité de faire cette application de différente manière mais pour ne pas prendre de mauvaises habitudes, je me tourne vers vous les expérimentés pour savoir quelle est la meilleure architecture selon vous.

    Pour illustrer mon propos, voici ce que fait mon application (dans les grandes lignes) :
    - Je me connecte à un serveur distant pour récupérer un flux d'information
    - Je traite le flux de différents types
    - J'affiche dans un gridview le résultat (titre, image)
    - Je permet d'avoir le détail (présentation détaillé différente en fonction du type d'info)

    J'ai donc trouvé 3 façons de faire ça :
    1 - La manière linéaire : mais pour cela il faut désactiver l'accès réseau en tache d'arrière plan.
    2 - La manière synchrone : en utilisant un thread (run , start, join) mais le temps d'aller chercher les éléments, l'application se lance avec l'écran "moche" pré paramétrer (puisque le oncreate se finit une fois les données traitées)
    3 - La manière asynchrone : AsyncTask (pour simplifier) mais cela implique cette fois de gérer des rafraichissements des écrans puisque les données arrivent après le premier affichage de l'écran

    Voilà ce qui m'intéresserait et probablement tous les débutants aussi c'est de savoir comment vous feriez vous par exemple sur ce type d'application.

    En espérant avoir été clair, je vous remercie par avance.

  2. #2
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    La 3ème méthode est la seule valable.

    La 1ère et la 2ème ont le même problème : elles gèlent l'interface, ce qui est à proscrire le plus possible.
    De plus, sur Android, elles déclencheront une exception : NetworkOnMainThreadException, qui porte bien son nom.

    Dans un premier temps, afficher des placeholder, ou une vue complète d'attente (éviter la popup "chargement" si possible), et afficher les données au fur et à mesure qu'elles arrivent, ou tout en un coup, dépendant de ce qui est le plus joli.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  3. #3
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2014
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2014
    Messages : 40
    Par défaut
    @Hizin : pourrais tu être un peu plus précis dans ton architecture (c'est justement là où j'ai un peu de mal avec la compronête).
    Je veux dire, le choix serait donc d'utiliser AsyncTask :
    Tu récupères donc les données dans l'AsyncTask.
    Tu met le Gridview où ? (dans le mainactivity quand même ? si oui comment gères tu le rafraîchissement ?)
    Gères tu de manière particulière la navigation (retour à l'écran précédent par exemple) => fais tu appel à des services systématiquement si oui y a t il une façon de faire particulière ?

  4. #4
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Ca va dépendre justement de tes vues.

    De ce que je comprends : tu as une gridview composée de multiples éléments complexes. Chaque éléments complexes est un agrégat d'un texte et d'une image.
    Pour se faire, je passerai plutôt par une ListView, car ça y ressemble beaucoup (verticale ou horizontale).

    Je n'ai pas de "MainActivity". J'évite le plus possible les noms trop générique ou trop couplant. Chaque activité peut être lancée de n'importe où, il n'y en a donc pas une de "principale", elles le sont toutes.

    La vue sera gérée par une Activity, celle-ci se chargeant ensuite de lancer les AsyncTask.

    Dépendant de ce que tu désirs : soit une AsyncTask par élément complexe en notifiant la vue dans le onPostExecute retournant un POJO String/URL (ou String/Bitmap), la vue se débrouillant ensuite pour mettre ça où il faut (un pattern observer en somme, l'utilisation prévue pour une AsyncTask).
    Soit une AsyncTask générale, téléchargeant toutes les données puis notifiant la vue de se mettre à jour en créant les widgets qui vont bien et les mettant où il faut.

    Pour le "retour", je ne peux pas vraiment te répondre. Tu n'as présenté que le cas d'une vue statique sans interaction comportant textes et images.

    J'imagine qu'un toucher ouvre une autre activité, c'est bien ça ?
    Dans ce cas, il faut faire attention aux erreurs OutOfMemory à cause des images. Les données doivent être stockées pour ne pas avoir à refaire les requêtes (il faut penser au forfait data des utilisateurs), mais plus dans un système de cache locale que gardées en mémoire vive si elles sont "volumineuses".
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  5. #5
    Membre extrêmement actif
    Profil pro
    Développeur
    Inscrit en
    Mars 2012
    Messages
    1 970
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 970
    Par défaut
    Citation Envoyé par Hizin Voir le message
    La 3ème méthode est la seule valable.

    La 1ère et la 2ème ont le même problème : elles gèlent l'interface, ce qui est à proscrire le plus possible.
    De plus, sur Android, elles déclencheront une exception : NetworkOnMainThreadException, qui porte bien son nom.

    Dans un premier temps, afficher des placeholder, ou une vue complète d'attente (éviter la popup "chargement" si possible), et afficher les données au fur et à mesure qu'elles arrivent, ou tout en un coup, dépendant de ce qui est le plus joli.
    Concernant la méthode 2 (Thread):
    Si tu lances ton thread dans un Service ça ne gèle pas l'interface
    Ce qui veut dire que tu as une 4eme option (les services).

  6. #6
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2014
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2014
    Messages : 40
    Par défaut
    C'est exactement ça merci. Disons qu'en l'état de mes connaissances, ce qui me bloque ("bloquait ?"), c'est la notion de "widget qui va bien" que je ne dois pas maitriser comme il faut car je me retrouve toujours dans le cas où j'affiche d'abord la view puis j'obtiens les données (normal je suis en asynchrone) et puis après ... je met à jour et donc pendant ce laps de temps, j'ai une vue à gérer.

    J'ai remarqué que sur des applis type sport24, ils avaient choisi d'afficher pendant ce laps de temps les données anciennement conservées (ce que je peux faire puisque que je les sauvegarde en local). Est ce un choix qui te semble valable ?

    Sinon, oui je passe d'une activity (dites main parce que c'est la première) qui gère mon gridview (donc toi tu me conseilles de sortir le gridview et le mettre dans une autre activity) puis j'appelle une autre view (detail) dans une autre activity qui est appelé sur le fait de toucher l'image. Maintenant, je ne sais pas encore retourner sur le gridview quand l'utilisateur touche au retour de son smartphone (c'est pour ça que je parlais de navigatoin).

    Merci j'y vois plus clair.

    @hotcryx : dans ce cas quelle est la différence entre lancer un async et un thread lancé dans un service ? (je sais je suis un peu boulet) ça évite de lancer une autre activity ?

  7. #7
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    J'ai remarqué que sur des applis type sport24, ils avaient choisi d'afficher pendant ce laps de temps les données anciennement conservées (ce que je peux faire puisque que je les sauvegarde en local). Est ce un choix qui te semble valable ?
    Oui, avec un retour utilisateur indiquant que les données sont en train de se rafraîchir.

    (donc toi tu me conseilles de sortir le gridview et le mettre dans une autre activity)
    Non, absolument pas. Ton Activity gère la gridview... mais la laisse vide tant qu'elle n'a aucune données à afficher. Ensuite, quand tu reçois un jeu texte+image, tu l'affiches, selon le design pattern observer ( https://en.wikipedia.org/wiki/Observer_pattern ).

    Pour le retour : Android le gère nativement.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  8. #8
    Membre extrêmement actif
    Profil pro
    Développeur
    Inscrit en
    Mars 2012
    Messages
    1 970
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Mars 2012
    Messages : 1 970
    Par défaut
    Greedo1 => si la tâche est uniquement du background (pas d'interaction avec l'UI thread), je crois que je ne prends pas trop de risque en disant haut et fort que l'utilisation d'un Thread est le plus adapté

    Et pourquoi les encapsuler dans un service?
    l'un des avantage du service est qu'il démarre/stoppe tout seul et que c'est effectivement une tâche pouvant être utilisée de multiples fois et en même temps.

    On peut également partager le service avec d'autres applications
    (pas encore testé)

  9. #9
    Membre confirmé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Octobre 2004
    Messages : 92
    Par défaut
    Salut tout le monde.
    @ Hizin ,
    est ce que c'est possible d'avoir un petit exemple de remplissage d'un Grid View, en utilisant un AsyncTask pour interrogé la base distante , et le tout avec le pattern observer.
    Cordialement.

  10. #10
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Désolé, je n'ai actuellement pas du tout le temps de réaliser un proto.
    Peut-être qu'une autre bonne âme l'aura, mais j'ai uniquement le temps de donner de rapides conseils et directions actuellement.
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  11. #11
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2014
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2014
    Messages : 40
    Par défaut
    Citation Envoyé par SaladinDev Voir le message
    Salut tout le monde.
    @ Hizin ,
    est ce que c'est possible d'avoir un petit exemple de remplissage d'un Grid View, en utilisant un AsyncTask pour interrogé la base distante , et le tout avec le pattern observer.
    Cordialement.
    Je peux te mettre où j'en suis. J'ai tout remis comme Hizin le préconise.
    J'ai donc :
    - l'accès http en async (principe httprequest que tu peux utiliser ou changer en appel base de données)
    - le chargement des images dans le gridview en async aussi
    - et donc la construction d'un gridview (image + texte)
    J'ai pas le pattern observer (je l'ai mis mais je ne l'ai pas encore bien compris donc ça marche pas).

    Si ça t'intéresse ...

  12. #12
    Modérateur
    Avatar de Hizin
    Homme Profil pro
    Développeur mobile
    Inscrit en
    Février 2010
    Messages
    2 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur mobile

    Informations forums :
    Inscription : Février 2010
    Messages : 2 180
    Par défaut
    Le pattern Observer est l'un des plus simples

    Il consiste en deux rôle : un observant, et un observé.

    L'observant s'enregistre auprès de l'observé. L'observé informe l'observant lorsqu'il change. C'est aussi simple que ça
    C'est Android, PAS Androïd, ou Androïde didiou !
    Le premier est un OS, le second est la mauvaise orthographe du troisième, un mot français désignant un robot à forme humaine.

    Membre du comité contre la phrase "ça marche PAS" en titre et/ou explication de problème.

    N'oubliez pas de consulter les FAQ Android et les cours et tutoriels Android

  13. #13
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2014
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2014
    Messages : 40
    Par défaut
    Le truc c'est que je ne maitrise pas les relations entre activity ? fichiers ?

    Je veux dire, j'ai ma mainActivity qui gère le gridview et j'ai donc déclarer le pattern observer et l'ai lancé (...thread.start...),
    dans l'EventSource, j'ai fait l'appel http qui me retourne dans le ResponseHandler le flux en retour.

    Et maintenant, comment je lance le rafraichissement du gridview puisque ma classe MyAdapter est dans mon mainactivity ? (comme j'ai déjà dit je crois que je suis complètement parasité par la programmation non objet).

    En gros j'ai que ça dans ma mainactivity :

    final EventSource eventSource = new EventSource();
    final ResponseHandler responseHandler = new ResponseHandler();
    eventSource.addObserver(responseHandler);
    Thread thread = new Thread(eventSource);
    thread.start();

    et je suppose qu'il faut que je mette quelque chose du type gridView.setAdapter(new MyAdapter(this)); quelque part non ?

    (merci pour ta patience au passage)

  14. #14
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2014
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2014
    Messages : 40
    Par défaut
    Bien, je vous fait un petit retour sur mon expérience.

    Mon problème venait bien de ma déformation de développeur non objet, au final, je n'ai pas utilisé de pattern observer car je n'en avais pas besoin.
    Mon problème était très simple, j'appelai "gridView.setAdapter(new MyAdapter(this));" directement dans mon onPostExecute de mon asynctask en essayant de déclarer les différentes composantes en public alors qu'il suffisait de mettre cette ligne dans une fonction public et d'appeler cette fonction.

    Donc maintenant tout fonctionne bien mais je voudrais optimiser un peu mon application et pour cela j'ai besoin d'être sûr d'avoir bien compris les différentes composantes de mes développements, j'aurai donc trois questions supplémentaires :

    1 - Gestion des AsyncTask :
    J'ai donc un asynctask principale qui est appelé et à l'intérieur de celle-ci j'ai une autre asynctask appelée de manière succéssives pour m'afficher mes images distantes.
    Suivant la lenteur du réseau, que se passe t il lors de deux appels successifs d'une même asynctask ? le premier appel est il stoppé par le second ? (je pense que non mais je voudrais confirmation).

    2 - Gestion des flux de données :
    Je récupère donc des images distantes que j'affiche ensuite dans mon gridview, j'ai remarqué quelques lenteurs depuis la finalisation de mon développement et la mise en place de l'appel de la fonction ?
    Est ce du à une mauvaise gestion de la mémoire ou est ce du à la taille de mes images qui sont actuellement brutes (150ko) ou les deux ?
    (je vais bien évidemment améliorer cela, ma réflexion tourne surtout autours de la notion de gestion mémoire => ça provoque des lenteurs ou ça provoque des plantages en général ?)

    3 - Une gestion d'un retour dans le postexecute d'une asynctask est il plus rapide qu'un pattern observer ? (je pense que oui mais je me trompe peut être).

    Merci à tous pour vos aides et si quelqu'un a besoin de voir ce que j'ai fait, pas de soucis.

    EDIT : grosse boulette de ma part en plus => ne pas oublier : gridView.invalidateViews(); et la ... plus de lenteur

  15. #15
    Membre confirmé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Octobre 2004
    Messages : 92
    Par défaut
    On lisant les commentaires , je pense que j'utilise mal la classe AsyncTask :
    Voici ma classe
    Code Java : 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
     
    public class MyAsynTask extends AsyncTask<Void, integer, String> {
     
    	private ArrayList<NameValuePair> parameter;
    	private String servletName;
    	private String requestResult;
     
    	public MyAsynTask() {
    		this.parameter = new ArrayList<NameValuePair>();
    		this.servletName = "";
    		this.requestResult = "";
    	}
     
    	public MyAsynTask(String servletName) {
    		this.parameter = new ArrayList<NameValuePair>();
    		this.servletName = servletName;
    		this.requestResult = "";
    	}
     
    	@Override
    	protected String doInBackground(Void... request) {
    		try {
    			requestResult = CustomHttpClient.executeHttpPost(servletName, parameter);
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return requestResult;
    	}
     
    	public void setServletName(String servletName){
    		this.servletName = servletName ;
    	}
     
    	public void addParametres(String key,String value){
    		parameter.add(new BasicNameValuePair(key, value));
    	}
     
    	public void clearParametres(){
    		parameter.clear();
    	}
     
    	public String getRequestResult(){
    		return requestResult ;
    	}
     
    }

    et je l'utilise comme ça :
    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    MyAsynTask asyncTask = new MyAsynTask(nom_servlet_destination);
    asyncTask.addParametres(nom_parametre, valeur_parametre);
    String rep = asyncTask.execute().get();
    j'ai une seule classe pour tout mon projet ,et je l’instancie à chaque fois que j'en ai besoin.

  16. #16
    Membre averti
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juillet 2014
    Messages
    40
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juillet 2014
    Messages : 40
    Par défaut
    Voilà mon Fichier MainActiviy.java :

    Alors rapidement :
    => Class MainAcitivity : cela te donne comment je fais les appels
    => RecupAdrImage : permet de filtrer le chemin d'une image dans un texte s'il y en a un (pas forcément utile pour toi)
    => MyAdapter : gère l'affichage du gridview
    => getBitmapFromURL : ramène l'image pour la mettre dans le gridview (appelée en asynctask par l'adapter)
    => sauvegarde : sauvegarde les données en local pour le premier chargement ou s'il n'y a pas de réseau
    => Recupdonnees : récupère les données sauvegardées en local (à améliorer en la mettant en global pour toute l'application mais j'arrive pas à la passer en static)
    => isNetworkAvailable : une fonction récupérée qui teste si le réseau est dispo ou non
    => GetData : la tache asynctask qui permet de récupérer les données en http
    => Affichage : gère l'affichage/rafraichissement du gridview (obligé de l'encapsuler pour pouvoir l'appeler de GetData en fin d'exécution)
    => BitmapFromURL : récupération de l'image en asynctask puisqu'il n'est pas possible de le faire directement dans MainActivity (accès réseau pour télécharger l'image)

    Si tu as besoin d'infos, n'hésites pas.

    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
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
     
    public class MainActivity extends ActionBarActivity 
    {
    	private TextView tv;
    	private String donnees = "";
    	private GridView gridView;
    	private String[] tab_news = null;
    	@Override
        protected void onCreate(Bundle savedInstanceState) 
        {
    		//StrictMode.ThreadPolicy policy = new StrictMode.
    		//ThreadPolicy.Builder().permitAll().build();
    		//StrictMode.setThreadPolicy(policy);
     
    		// retire les titres en haut de page
    		requestWindowFeature(Window.FEATURE_NO_TITLE);
    		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
     
    		super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
     
            tv = (TextView) findViewById(R.id.textView1);
    		gridView = (GridView)findViewById(R.id.gridview);
     
     
    		if(isNetworkAvailable()) new GetData(tv).execute("");
     
    		Affichage();
     
            gridView.setOnItemClickListener(new OnItemClickListener() 
            { // listener sur le clic pour plus tard
               public void onItemClick(AdapterView<?> parent, View v, int position, long id) 
               {
                  	Bundle objetbunble = new Bundle();
                  	objetbunble.putString("numero", Integer.toString(position));
                  	objetbunble.putString("donnees", donnees);
                  	Intent intent = new Intent(MainActivity.this, detail.class);
            	   	intent.putExtras(objetbunble);
               		startActivity(intent);
               }
            });
        }
     
    	private String RecupAdrImage(String param)
    	{// récupère l'adresse de l'image dans un texte
    		String retour = "";
    		int j = param.indexOf("src=");
    		int k = -1;
    		if(j != -1) k = param.indexOf((char)34, j+6);
     
    		if( (j != -1)&&(k != -1) )
    		{
    			retour = param.substring(j+5, k); // -j-5
    			if(retour.indexOf("./") != 1) retour = retour.replace("./", "http://www.hbcnancysluc.com/");
    			retour = retour.replace(" ", "%20"); // A voir si toujours utile ?
    		}
     
    		return retour;
    	}
     
    	private class MyAdapter extends BaseAdapter {
    	    private List<Item> items = new ArrayList<Item>();
    	    private LayoutInflater inflater;
     
    	    public MyAdapter(Context context) {
    	        inflater = LayoutInflater.from(context);
     
    	        String[] tab_ligne;
    	        String tmpImg = "";
    	        for(int i = 0; i < tab_news.length; i++)
    	    	    { 
    	    		  tab_ligne = tab_news[i].split("\\|");
    	    		  tmpImg = RecupAdrImage(tab_ligne[2]);
    	    		  if(tab_ligne[1].length() > 26) items.add(new Item(tab_ligne[1].substring(0,26), R.drawable.news, tmpImg));
    	    		  else items.add(new Item(tab_ligne[1], R.drawable.news, tmpImg));
     
    	    		  if(i == 2)
    	    		  { // cas particulier du bouton convocation (qui n'est pas une news)
    	    			  items.add(new Item("", R.drawable.convocation, null));
    	    		  }
    	    	    }
     
    	    }
     
    	    @Override
    	    public int getCount() {
    	        return items.size();
    	    }
     
    	    @Override
    	    public Object getItem(int i) {
    	        return items.get(i);
    	    }
     
    	    @Override
    	    public long getItemId(int i) {
    	        return items.get(i).drawableId;
    	    }
     
    	    @Override
    	    public View getView(int i, View view, ViewGroup viewGroup) {
    	        View v = view;
    	        ImageView picture;
    	        TextView name;
     
    	        if(v == null) {
    	            v = inflater.inflate(R.layout.gridfile, viewGroup, false);
    	            v.setTag(R.id.picture, v.findViewById(R.id.picture));
    	            v.setTag(R.id.text, v.findViewById(R.id.text));
    	        }
     
    	        picture = (ImageView)v.getTag(R.id.picture);
    	        name = (TextView)v.getTag(R.id.text);
     
    	        Item item = (Item)getItem(i);
     
    	        picture.setImageResource(item.drawableId);
    	        if(item.image != "") 
            	{
    	        	new BitmapFromURL(picture, item.image).execute("");
            	}
    	        name.setText(item.name);
    	        if(item.name == "") name.setVisibility(View.INVISIBLE);
    	        return v;
    	    }
     
    	    private class Item {
    	        final String name;
    	        final int drawableId;
    	        final String image;
     
    	        Item(String name, int drawableId, String tmpImg) {
    	            this.name = name;
    	            this.drawableId = drawableId;
    	            this.image = tmpImg;
    	        }
    	    }
    	}
     
    	private Bitmap getBitmapFromURL(String src) {
    	    try { // téléchargement de l'image distante
    	        java.net.URL url = new java.net.URL(src);
    	        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    	        connection.setDoInput(true);
    	        connection.connect();
    	        InputStream input = connection.getInputStream();
    	        Bitmap myBitmap = BitmapFactory.decodeStream(input);
    	        return myBitmap;
    	    } catch (IOException e) {
    	        e.printStackTrace();
    	        return null;
    	    }
    	}
     
    	private void sauvegarde()
    	{ // sauvegarde des données en local
    		String FILENAME = "fichierdedonnees";
    		String string = (String) tv.getText();
    		FileOutputStream fos;
    		try {
    			fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
      			fos.write(string.getBytes());
      			fos.close();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		//tv.setVisibility(View.VISIBLE);
    	}
     
    	public String Recupdonnees()
    	{ // lecture des données enregistrées en local
    		String retour = null;
     
    		FileInputStream in;
    		try {
    			in = openFileInput("fichierdedonnees");
    			InputStreamReader inputStreamReader = new InputStreamReader(in);
    		    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
    		    StringBuilder sb = new StringBuilder();
    		    String line;
    		    while ((line = bufferedReader.readLine()) != null) {
    		        sb.append(line);
    		    }
    		    retour = sb.toString();
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
     
    		return retour;
    		//tv.setVisibility(View.VISIBLE);
    	}
     
        private boolean isNetworkAvailable() {
            ConnectivityManager cm = (ConnectivityManager) 
              getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = cm.getActiveNetworkInfo();
            // si aucun réseau n'est disponible, networkInfo sera null
            // sinon, vérifier si nous sommes connectés
            if (networkInfo != null && networkInfo.isConnected()) {
                return true;
            }
            return false;
        }
     
        private class GetData extends AsyncTask<String, Void, String> {
    		private TextView display;
    		GetData(TextView view){
    		    this.display = view;
    		}
     
    		@Override
    		protected String doInBackground(String... message) {
    			// appel distant
    			HttpClient httpclient;
    		    HttpGet request;
    		    HttpResponse response = null;
    		    String result = " ";
     
    		    try {
    		        httpclient = new DefaultHttpClient();
                           // mettre en dessous l'url qui génère les données (ici en format brût, tu peux utiliser aussi du JSON)
    		        request = new HttpGet("http://www.tonsite.com/test.php");
    		        response = httpclient.execute(request);
    		    }
    		    catch (Exception e) {
    		        result = "erreur appel http";
    		    }
     
    		    try {
    			       Reader reader = (new InputStreamReader(response.getEntity().getContent()));
    		    		try {
    						StringBuilder sb = new StringBuilder();
    						char[] cbuf = new char[8192];
    						int len;
     
    						while ( (len=reader.read(cbuf)) > 0 ) {
    							sb.append(cbuf, 0, len);
    						}
    						result = sb.toString();
    					} finally {
    						reader.close();
    					}
     
     
     
    				    } catch (Exception e) {
    				        result = "erreur import des données";
    				    }
    		    return result;
    		}
     
    		protected void onPostExecute(String result) {
    			// traitement de retour => l'utilisation du textview n'est plus utile mais ça m'a été utile pour le debuggage
    		    this.display.setText(result);
    		    sauvegarde();
    		    MainActivity.this.Affichage();
    		}
    	}
     
        public void Affichage()
        {
        	donnees = Recupdonnees();
    		if(donnees != "")
    		{// Traitement des données
        	   // préférence à stocker = |idt1|idt2| => idt1, idt2 a exclure A FAIRE (dans un autre fichier ?)
        	   String[] tab_donnees = donnees.split("\\|-\\|");
        	   String[] tab_categories = tab_donnees[0].split("\\|°\\|");
        	   String[] tab_result = tab_donnees[1].split("\\|°\\|");
        	   tab_news = tab_donnees[2].split("\\|°\\|");
    		}
    		gridView.invalidateViews();
        	gridView.setAdapter(new MyAdapter(this));
     
        }
     
        private class BitmapFromURL extends AsyncTask<String, Void, Bitmap> {
    		private ImageView picture;
    		private String chemin;
    		BitmapFromURL(ImageView view, String param){
    		    this.picture = view;
    		    this.chemin = param;
    		}
     
    		@Override
    		protected Bitmap doInBackground(String... message) 
    		{
    			Bitmap result = null;
    			result = getBitmapFromURL(chemin);
    			return result;
    		}
     
    		protected void onPostExecute(Bitmap result) {
    		    if(result != null) this.picture.setImageBitmap(result);
    		}
    	}
     
    }

  17. #17
    Membre confirmé
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    92
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Octobre 2004
    Messages : 92
    Par défaut
    J'ai modifié l'utilisation de ma classe AsyncTask en utilisant le pattern observer (j'ai crée mes propres interfaces pour Observer et Observable) et j'aimerai savoir ce que vous en pensez :
    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
     
    public class MyAsynTask extends AsyncTask<Void, integer, String> implements
    		Observable {
     
    	private ArrayList<NameValuePair> parameter;
    	private String servletName;
    	private String requestResult;
    	private ArrayList<Observer> listeObserver;
     
    	public MyAsynTask() {
    		this.parameter = new ArrayList<NameValuePair>();
    		this.servletName = "";
    		this.requestResult = "";
    		this.listeObserver = new ArrayList<Observer>();
    	}
     
    	public MyAsynTask(String servletName) {
    		this.parameter = new ArrayList<NameValuePair>();
    		this.servletName = servletName;
    		this.requestResult = "";
    		this.listeObserver = new ArrayList<Observer>();
    	}
     
    	@Override
    	protected String doInBackground(Void... request) {
    		try {
    			requestResult = CustomHttpClient.executeHttpPost(servletName,
    					parameter);
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return requestResult;
    	}
     
    	@Override
    	protected void onPostExecute(String result) {
    		notifyObserver(result);
    	}
     
    	public void setServletName(String servletName) {
    		this.servletName = servletName;
    	}
     
    	public void addParametres(String key, String value) {
    		parameter.add(new BasicNameValuePair(key, value));
    	}
     
    	public void clearParametres() {
    		parameter.clear();
    	}
     
    	public String getRequestResult() {
    		return requestResult;
    	}
     
    	@Override
    	public void addObserver(Observer o) {
    		listeObserver.add(o);
    	}
     
    	@Override
    	public void removeObserver(Observer o) {
    		listeObserver.remove(o);
     
    	}
     
    	@Override
    	public void notifyObserver(String result) {
    		for (int i = 0; i < listeObserver.size(); i++) {
    			Observer o = listeObserver.get(i);
    			o.update(this,result);
    		}
    	}
     
    }
    et j'herite de cette classe comme suite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class ProduitAsynTask extends MyAsynTask {
     
    	public ProduitAsynTask(){
    		super("ProduitServlet");
    	}
     
    }
    et j'ai une activity qui contient deux GridView :
    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
    public class ProduitActivity extends Activity implements Observer {
     
    	private GridView gridFamille ;
    	private GridView gridProduit;
    	private ArrayList<HashMap<String, String>> familleItem = new ArrayList<HashMap<String,String>>();
    	private ArrayList<HashMap<String, String>> produitItem = new ArrayList<HashMap<String,String>>();
    	private SimpleAdapter familleAdapter ;
    	private SimpleAdapter produitAdapter ;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_produit);
    		FamilleAsynTask famAsyncTask = new FamilleAsynTask();
    		famAsyncTask.addObserver(this);
    		famAsyncTask.addParametres("action", "getAll");
    		famAsyncTask.execute();
    		gridFamille = (GridView) findViewById(R.id.gridViewFamille);
    		familleAdapter = new SimpleAdapter(this.getBaseContext(),
    				familleItem, R.layout.affiche_famille_produit, new String[] {
    						"CODE", "DESIGNATION" }, new int[] { R.id.hdn_txt_code,
    						R.id.txv_des });
    		gridFamille.setAdapter(familleAdapter);
    		gridFamille.setOnItemClickListener(onFamilleProduitClick);
     
    		gridProduit = (GridView) findViewById(R.id.gridViewProduit);
     
    	}
     
    	private OnItemClickListener onFamilleProduitClick = new OnItemClickListener() {
     
    		@Override
    		public void onItemClick(AdapterView<?> av, View v, int p, long i) {
    			String rep = "";
    			HashMap<String, String> hmFamille = (HashMap<String, String>) av
    					.getItemAtPosition(p);
    			String codeFamille = hmFamille.get("CODE");
    			ProduitAsynTask prodAsynTask = new ProduitAsynTask();
    			prodAsynTask.addObserver(ProduitActivity.this);
    			prodAsynTask.clearParametres();
    			prodAsynTask.addParametres("action", "getProduitsByFamille");
    			prodAsynTask.addParametres("codeFamille", codeFamille);
    			prodAsynTask.execute();
    		}
     
    	};
     
    	public void update(Observable o, String result) {
    		JSONArray jsonArray = null;
    		try {
    			jsonArray = new JSONArray(result);
    		} catch (JSONException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		if( o instanceof FamilleAsynTask){
    			familleItem.clear();
    			familleItem = Helper.jsonToArrayList(jsonArray);
    			familleAdapter = new SimpleAdapter(this.getBaseContext(),
    					familleItem, R.layout.affiche_famille_produit, new String[] {
    							"CODE", "DESIGNATION" }, new int[] { R.id.hdn_txt_code,
    							R.id.txv_des });
    			gridFamille.setAdapter(familleAdapter);
    		}else if( o instanceof ProduitAsynTask){
    			produitItem.clear();
    			produitItem = Helper.jsonToArrayList(jsonArray);
    			produitAdapter = new SimpleAdapter(this.getBaseContext(),
    					produitItem, R.layout.affiche_produit, new String[] {
    							"CODE", "DESIGNATION","PRIX_MP" }, new int[] { R.id.CODE,
    							R.id.DESIGNATION ,R.id.PRIX_MP});
    			gridProduit.setAdapter(familleAdapter);
    		}
    	};
     
     
    }

Discussions similaires

  1. architecture des applications windows azure
    Par malouch dans le forum Microsoft Azure
    Réponses: 1
    Dernier message: 24/09/2011, 08h16
  2. Répertoire d'installation des applications Android
    Par Eriatolc dans le forum Android
    Réponses: 3
    Dernier message: 13/05/2011, 10h02
  3. Versioning automatique des applications android
    Par titou624 dans le forum Android
    Réponses: 8
    Dernier message: 26/04/2010, 22h46
  4. Developper des applications Android pour Netbook ?
    Par LeMeD dans le forum Android
    Réponses: 0
    Dernier message: 25/01/2010, 15h45
  5. Réponses: 5
    Dernier message: 21/08/2008, 20h20

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