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

Composants Java Discussion :

Optimisation d'un ListCellRenderer


Sujet :

Composants Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut Optimisation d'un ListCellRenderer
    Bonjour, je développe depuis quelques temps une application java sur mon temps perso.

    J'ai 2 listes, l'une contenant les discussions sms d'un téléphone portable, à droite le contenu de la conversation.

    Lors d'un clique sur une discussion, on charge son contenu dans la liste de droite.

    Le renderer (ListCellRenderer) dessine des bulles (style iPhone) en fonction de la taille du sms, cette opération est je pense très coûteuse en terme de performance. Pour une discussion de 300 sms le chargement est à peine d'une seconde. Pour 10 000 sms, le chargement est de plus de 10 secondes.

    Je cherche donc un moyen d'optimisé tout ça.

    J'ai remarqué lors d'un chargement que toutes les bulles SMS était construite au chargement, puis il redessine uniquement les sms visible dans le jscrollpane. L'idée serais d'éviter ce chargement coûteux (10 000 bulles à dessiné forcement sa prend du temps :p)

    Voici un screenshot pour illustrer l'application : http://remoteanything.mobi/wp-conten...gingScreen.jpg


    Si vous avez des idées pour améliorer le temps de chargement
    Merci à vous

  2. #2
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Le problème est complexe...


    Le problème c'est que la JList à besoin d'initialiser tous ses composants avec le CellRenderer afin de connaitre leurs tailles. Ceci afin de pouvoir déterminer sa propre taille.


    Donc déjà il faudrait voir le code de ton CellRenderer, afin de déterminer s'il n'y a pas des choses inutiles...



    Un moyen simple pour éviter cela serait de donner une taille fixe à tous tes éléments avec setFixedCellWidth() and setFixedCellHeight(), voir même avec setPrototypeCellValue().
    Le problème c'est justement que tous les messages auront la même taille... ce qui n'est pas forcément esthétique... :/



    Un autre moyen consisterait à remplir la liste petit à petit.
    Plutôt que d'y charger les 300 ou 10000 SMS, tu n'en charges que les 10 derniers, et tu ajoutes les 10 suivants lorsque la scrollbar atteint le dernier élément...

    Le temps de chargement devrait moins se faire sentir... mais c'est bien plus complexe à mettre en place :/


    a++

  3. #3
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Cela pourrait également venir de la façon dont tu dessines ces bulles...

    As tu mis les images dont tu te sers en cache, ou les recharges tu à chaque fois?

    Recalcules tu à chaque fois le gradient lié à tes bulles, ou fais tu simplement un redimensionnement?

    Ton code (renderer +composant custom) pourrait nous donner des informations sur la source du problème...

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 7
    Par défaut
    Merci pour vos réponses

    @adibuga: Tu a très bien compris le problème, j'avais déja essayé les fixedcells mais j'ai fini par comprendre que c'était une impasse du fait de la taille variable des SMS (bien que le chargement des bulles était devenu plus rapide).

    Je pense que je vais opter pour la solution que tu a proposé, je vais écouter la position du scroll et charger les SMS 50 par 50.

    @Sinok: Les images des bulles originales sont mis en cache au chargement de l'application. Je calcule d'abord la taille de la bulle à partir du body du sms. Ensuite je redimensionne l'image en cache pour l'adapter au sms. Puis ensuite je dessine le texte par dessus la bulle.

    Voici une partie du code
    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
    public class BalloonMessageRenderer extends JLabel implements ListCellRenderer {
     
        TchatConfig _config = null;
     
        @Override
        public Component getListCellRendererComponent(JList list, Object obj, int index, boolean isSelected, boolean cellHasFocus) {
            Message curMsg = (Message) obj;
     
            _config = TchatConfigBuilder.getInstance().getTchatConfig(curMsg.getThreadId());
            Balloon balloon = new Balloon(curMsg, list.getWidth);
            if (balloon != null && balloon.getImage() != null) {
                setIcon(new ImageIcon(balloon.getImage()));
                setSmsPosition(curMsg.isEmmit());
                setFont(_config.getDateFont());
                setForeground(_config.getDateColor());
                setTextDate(index, list, curMsg);
                setOpaque(false);
            }
            return this;
        }}
     
    public class Balloon extends MessageDrawer {
     private void buildSmsBalloon() throws IOException {
            String body = ((Sms) _msg).getBody();
            int column = getColumn(body, _widthDefault);
            int row = getRow(((Sms) _msg).getBody(), column);
            int height = _metrics.getHeight();
            if(row == 1 && height < 20){
            }else{
                row = (row * height) - 14;
            }
            //Redimensionne une bulle au dimension demandé
            balloonBuilder(row, column);
            //Dessine le texte sur la nouvelle image
            writeString(((Sms) _msg).getBody(), getXBorder(), 3,     _config.getBodyFont());
            addIconProperties();
        }
    }
     
    public class MessageDrawer extends JLabel {
     protected void writeString(String text, int xStart, int yStart, Font font) {
            Graphics2D graf = _image.createGraphics();
            graf.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            graf.setColor(_config.getBodyColor());
            graf.setFont(font);
     
            //cas où le texte du sms tiens sur plusieurs lignes
            if (getLenghtMsg(text) > _image.getWidth() - spaceBorder) {
                String stringTmp = text.trim();
                for (int i = 1; stringTmp.length() > 0; i++) {
                    //Determine la chaine de caractere adapter à la largeur de la bulle
                    String newString = StringUtil.cutter(stringTmp, _image.getWidth() - spaceBorder, _metrics);
                    //Dessine le texte sur la bulle
                    graf = drawMessage(graf, newString, xStart, (((_metrics.getHeight()) * i) + yStart));
                    if (newString.length() > 0) {
                        if (!newString.endsWith("-")) {
                            stringTmp = stringTmp.substring(newString.length()).trim();
                        } else {
                            stringTmp = stringTmp.substring(newString.length() - 1);
                        }
                    }
                }
            } else {
                graf = drawMessage(graf, text, xStart, _metrics.getHeight() + yStart);
            }
            //graf.dispose();
        }
    }
    Le code n'est sans doute pas très clair, j'ai écrit ça au tout début du projet et je crois bien que c'était la 1ere fois que j'utilisais les fonctions de dessin de Java. D'une certaine maniere, je suis convaincu que le code n'est pas tip top mais je suis egalement persuadé que malgrès de nombreuses optimisations sur la partie création de bulle, la solution la plus solide est de faire un chargement au fur et à mesure (soit via la position du scroll soit via un button) pour certains utilisateurs ont visiblement des discussions avec un nombre sms impressionnant et que le chargement de la discussion s'en fera toujours ressentir.

  5. #5
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Quelques remarques :

    Fais hériter ton renderer de DefaultListCellRenderer. Ce dernier étends lui aussi JLabel mais il redéfini avec un corps vide certaines méthodes inutiles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public class BalloonMessageRenderer extends DefaultListCellRenderer {
    Je ne vois pas trop l'intérêt de la classe Balloon dans le code que tu as donnée.
    La méthode buildSmsBalloon() n'est jamais appelé.

    Plus généralement la méthode getListCellRendererComponent() va être appelée très souvent. Évites d'y créer trop d'objets temporaires...


    a++

Discussions similaires

  1. Problème Optimisation ListCellRenderer
    Par Sebeee dans le forum Composants
    Réponses: 12
    Dernier message: 08/04/2013, 17h17
  2. Optimisation de votre SGBDR et de vos requêtes...
    Par SQLpro dans le forum Langage SQL
    Réponses: 35
    Dernier message: 11/01/2013, 11h49
  3. [VB6] [BDD] Optimisation de l'accès aux données
    Par LadyArwen dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 30/01/2003, 13h27
  4. [langage]Problème de temps de lecture, optimisation
    Par And_the_problem_is dans le forum Langage
    Réponses: 2
    Dernier message: 08/01/2003, 08h47
  5. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 2
    Dernier message: 11/06/2002, 10h24

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