INTERAÇÕES COM A UI Sonho de consumo são 60 FPS... A cada 16ms, um FPS certamente se perde Quanto mais FPSs perdidos, mais a experiência do usuário com a UI degrada...
GARBAGE COLLECTION Android 2.3+ implementa variante de CMS Pausas prolongadas e/ou frequentes durante a interação do usuário PRECISAM ser evitadas FORÇA PAUSAS DA UI THREAD PARA GC
AUTO BOXING ! Map map = new HashMap(); map.put(1024, "Android"); map.put(2048, "performance"); map.put(5096, "matters"); List values = new ArrayList(); values.add(3.1415);
SEMPRE ÓTIMO ??? ! StringBuilder builder = new StringBuilder(); for (int i = 0; i < count; i++) { builder.append("ANDROID"); } return builder.toString();
FATOS StringBuilder trabalha com um array de caracteres de tamanho pré-fixado... Estourar o limite significa criar um novo array de caracteres e concatenar no já existente...
BOAS PRÁTICAS final String androidRocks = "android" + "rocks"; ! ! ! ! ! ! ! // Nesse caso, constantes serão otimizadas // e concatenadas em tempo de compilação !!! final String facebookAvatarURL = GRAPH_BASE_URL.concat(facebookID); // String.concat() melhor para uma variável String StringBuilder builder = new StringBuilder(200); // Garantir que StringBuilder aloca caracteres suficientes // evita a criação de novos arrays de caracteres
public class BlocksEngine extends CCLayer { ! public void blocksEngine() { if (new Random().nextInt(300) == 0) { ! getDelegate().createBlock( new Block(Assets.block).generate(), 1, 1); } } } Um random por bloco Novo bloco a cada chamada da engine
public static final Random sRANDOM = new Random(); public class BlocksEngine extends CCLayer { ! public void blocksEngine() { if (sRANDOM.nextInt(300) == 0) { final Block b = BlocksPool.acquire(); // configurar seu bloco getDelegate().createBlock(b); } . . . BlocksPool.release(b); } } Random agora é constante Reuse um bloco previamente existente !!!
! private static final int MSG_DESIRED_EVENT = 0xb0b0; ! public void sendMessage(Handler handler, Object eventInfo) { final Message message = new Message(); message.what = MSG_DESIRED_EVENT; message.obj = eventInfo; handler.sendMessage(message); } Uma mensagem nova para cada evento de interesse
! private static final int MSG_DESIRED_EVENT = 0xb0b0; ! public void sendMessage(Handler handler, Object eventInfo) { final Message message = Message.obtain(); message.what = MSG_DESIRED_EVENT; message.obj = eventInfo; handler.sendMessage(message); } Obtém uma mensagem de um pool, ou cria uma nova
! List friends = new ArrayList(); ! if (users != null) { for (GraphUser user : users) { FacebookFriend friend = new FacebookFriend(user); friends.add(friend) } } Otimizada pelo compilador !!! FOR LOOP
PARCELLABLE E SERIALIZABLE Serializable é muito mais fácil de implementar Parcellable é muito mais eficiente na prática Serializable para um objeto Parcellable para coleções de objetos
! static class ViewHolder { public TextView friendName; public TextView friendStatus; public ImageView friendImage; } Cachear a posição de cada View na hierarquia de Views da linha ! CACHE DE OPERAÇÕES
LEMBRETES GERAIS EVITE annotations em tempo de execução EVITE malabarismos com java.lang.reflect OTIMIZE o acesso à suas variáveis http://developer.android.com/training/articles/perf-tips.html
private static final int MSG_DONE = 0xcafe; private Handler mHandler = new Handler(Looper.getMainLooper()); ! private void workOnBigFile(final String filePath) { ! new Thread(new Runnable() { @Override public void run() { Process.setThreadPriority( Process.THREAD_PRIORITY_BACKGROUND); ! File f = new File(filePath); Data d = DataUtils.extractFrom(f); Message.obtain(mHandler, MSG_DONE, d).sendToTarget(); } }).start(); } Prioridade mais baixa para sua Thread
PROBLEMAS COM ASYNCTASK Comportamento é inconsistente ao longo das versões de API do Android … Difícil para cancelar tarefas já executando em background ...
USANDO ASYNCTASK Assegure-se de que tarefas serão executadas em paralelo (backporting API14+) Use para TAREFAS CURTAS (segundos) Cuidados ao declarar como inner class ou ao associar callbacks
INTENT SERVICE Service com uma Thread Worker MUITO BOM para executar tarefas únicas Finaliza sozinho após o trabalho executado Callback mais burocrático após tarefa concluída
! public class HardWorkIntentService extends IntentService { ! public HardWorkIntentService() { super(“HardWorkIntentService”); } ! @Override protected void onHandleIntent(Intent intent) { // EXECUTE O SEU TRABALHO PESADO AQUI !!!! } ! } ! Intent toHardWork = new Intent(this, HardWorkIntentService.class); // Coloque seus parâmetros como extras! startService(toHardWork);
PROCESSAMENTO DE LAYOUTS Mais lento conforme Profundidade da hierarquia de Views Quantidade de Views por hierarquia Profilling via delay nos métodos onMeasure( ), onLayout( ), onDraw( )
OTIMIZAÇÕES EM LAYOUTS Pelo menos dois pontos básicos Conversão de declarações em XML em hierarquias Recuperação de itens dentro de uma hierarquia Precisamos de hierarquias mais leves e planas !!!
IMAGENS São redimensionadas em tempo de execução SEMPRE FORNEÇA TODOS OS CONJUNTOS DE IMAGENS Para imagens obtidas via IO, procure cachear os Bitmaps já processados