Bonnes pratiques du développement Android

Revue des bonnes pratiques et de quelques ui patterns

Qui suis-je ?

Jean-François GARREAU, Consultant IT SQLI

images/jf.jpg

Sommaire

Revoir son Java

images/LogoJava.png

Tout ce qu’on croit savoir est faux ;)

Oublions le Java

images/forget_java.jpg

AutoBoxing et types primitifs

Integer result = 1;
for (int i = 0; i < 10; i++){
 result += i;
}
return result;

Reviens à :

Integer result = new Integer(1);
for (int i = 0; i < 10; i++){
 result = new Integer(i + result.intValue());
}
return result.intValue();

Types primitifs

Il est donc préférable d’utiliser au maximum des types primitifs !

Attention cependant dans l’utilisation des types primitifs pour les nombres :

Les entiers sont en caches de -128 à 127

SparseArray

Sorte de HashMap avec des clés "entiers" dont l’ojbectif est d'éviter l’auto boxing

HashMap<Integer,String> map = new HashMap<Integer,String>();
map.put(550,"Echo");
map.put(551,"Echo");
map.get(550);

donne


HashMap<Integer,String> map = new HashMap<Integer,String>();
map.put(new Integer(550),"Echo");
map.put(new Integer(551),"Echo");
map.get(new Integer(550));

avec les sparseArray : pas d’auotboxing !

SparseArray<String> map = new SparseArray<String>();
map.put(550,"Echo");
map.put(551,"Echo");
map.get(550);

Gère aussi Booléens, Int en natif. La clé reste un entier !

Préférons les implémentations aux interfaces

List<String> list = new ArrayList<String>();

est à remplacer par


ArrayList<String> list = new ArrayList<String>();

On fait ça pour ménager la compilation

Ménageons la mémoire

Moins y en a mieux c’est

images/cofee_overload.jpg

Objectif : Instanciations minis !

Comment procédons nous pour faire le moins d’instanciations ?

  • Nous sommes sur des téléphones, la ram n’est pas une ressources forcément très présente.
  • Vous n'êtes pas la seule application !
  • Minimisons donc notre impact sur cette dernière.
    • Variables statiques
    • Réutilisation d’objets
    • Gestion des chaines de caratères
    • Layout allégé !
    • Gestion de l’autoboxing (cf précédement)

Préférons les variables statiques

Quand cela est possible bien entendu

  • L’utilisation de variables statiques permet d'économiser des instanciations.

public long doSomeStuff(int left, int top, int right, int bottom){
        return stuff(new Rect(left, top, right, bottom));
}

public abstract long stuff(Rect rect);

On peut faire mieux !


private static final Rect rect = new Rect();

public long doSomeStuff(int left, int top, int right, int bottom){
        rect.set(left, top, right, bottom);
        return stuff(rect);
}

public abstract long stuff(Rect rect);

Réutilisons des objets !


private static final int  MSG_ANIMATION_FRAME = 0xcafe;

public void sendMessage(Handler handler, Object userInfo){
        final Message message = new Message();
        message.what = MSG_ANIMATION_FRAME;
        message.obj = userInfo;

        handler.sendMessage(message);
}

Peut être remplacé par


private static final int  MSG_ANIMATION_FRAME = 0xcafe;

public void sendMessage(Handler handler, Object userInfo){
  final Message message = Message.obtain();
  message.what = MSG_ANIMATION_FRAME;
  message.obj = userInfo;

  handler.sendMessage(message);
}

ViewHolder

Réutilisation de vue sur les listView

  • pattern de réutilisabilité des vues

PAS BIEN !


public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View rowView = inflater.inflate(R.layout.rowlayout, parent, false);
    TextView textView = (TextView) rowView.findViewById(R.id.label);
    ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
    textView.setText(values[position]);
    // Change the icon for Windows and iPhone
    String s = values[position];
    if (s.startsWith("iPhone")) {
      imageView.setImageResource(R.drawable.no);
    } else {
      imageView.setImageResource(R.drawable.ok);
    }

    return rowView;
  }

ViewHolder

Réutilisation de vue sur les listView

BIEN !


public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = null;

        if (convertView == null){
            LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = inflater.inflate(R.layout.rowlayout, parent, false);
        }else{
                rowView = convertView;
        }
    TextView textView = (TextView) rowView.findViewById(R.id.label);
    ImageView imageView = (ImageView) rowView.findViewById(R.id.icon);
    textView.setText(values[position]);
    // Change the icon for Windows and iPhone
    String s = values[position];
    if (s.startsWith("iPhone")) {
      imageView.setImageResource(R.drawable.no);
    } else {
      imageView.setImageResource(R.drawable.ok);
    }

    return rowView;
  }

ViewHolder

Pourquoi donc ?

images/list_view_explain.jpg

Gestion des chaines de caratères

Layout allégés

Utiliser les balises merges pour réutiliser des layouts

Ui patterns

images/ActionBar2.png

Action Bar

DashBoard

NavigationDrawer

  • Nav 1
  • Nav 2
  • Nav 3

PullToRefresh

Pull down to refresh...
  • Pretty row 1
  • Pretty row 2
  • Pretty row 3
  • Pretty row 4
  • Pretty row 5
  • Pretty row 6
  • Pretty row 7
  • Pretty row 8
  • Pretty row 9
  • Pretty row 10
  • Pretty row 11
  • Pretty row 12
  • Pretty row 13
  • Pretty row 14
  • Pretty row 15
  • Pretty row 16
  • Pretty row 17

QuickActions

ViewPager

  • page1
    page2
  • page1
    page2
    page3
  • page2
    page3

Fragments

Bonnes Pratiques

images/yoda.jpg

Optimisons la bande passante !

Il vaut mieux faire n petits téléchargement ou 1 gros ?

images/cookie_model.png

Optimisons la bande passante

Un seul !

Reto Meier Google IO 2012 : à partir de 20:00

On passe les détails mais ça économise la batterie avec les ouvertures de connexions.

Optimisions la bande passante

Améliorons l’expérience utilisateur

N’attendons pas qu’il nous demande l’information

  • Utilisation des Broadcastreciever !
    • Application beaucoup plus réactive
    • L’utilisateur a une sensation de rapidité !

a utilser bien sur si cela est possible ;)

Améliorons l’expérience utilisateur

Ne pas bloquer le thread UI
Ne pas bloquer le thread UI
  • Ok mais Comment ?

Ne pas bloquer l’ui Thread

Gagnons en place

Nous sommes sur des réseaux téléphoniques pas toujours fournis en 4G, donc il faut ménager le poids de nos applications !

images/d9p.png

Ne pas hésiter non plus à créer programatiquement des drawables La partie du bas permet de définir la zone où mettre le contenu !

Librairies

Quoi utiliser et pourquoi ?

images/android_lib.jpg

Pourquoi ?

images/meme_enjeux.jpg

Librairies Google

Dans playservice, on va trouver des choses commes mapssV2, la sécurisation des apps

ActionBarSherlock

images/abs.png

ACRA

images/acra.png

RoboSpice Ou Volley

images/robospice.png

Injections de dépendances

images/android_annotations.png images/roboguice.png

Les librairies ça à l’air simple !

images/meme_solutions.jpg

Oui mais pas trop en fait… car pb d’héritage pb avec Maven, …

Merci

images/fond_merci.png

http://goo.gl/ebkxz

images/twitter-icon.png images/google-Plus-icon.png