63
DICAS PARA INTERFACES PERFORMÁTICAS NO SEU APP ANDROID INTEL SOFTWARE DAY 2013

Dicas para Interfaces Performáticas no seu App Android

Embed Size (px)

DESCRIPTION

Slides sobre dicas para interfaces Android mais responsivas, que utilizei na minha apresentação do Intel Software Day 2013

Citation preview

Page 1: Dicas para Interfaces Performáticas no seu App Android

DICAS PARA INTERFACES PERFORMÁTICAS

NO SEU APP ANDROID INTEL SOFTWARE DAY 2013

Page 2: Dicas para Interfaces Performáticas no seu App Android

CONTEXTO

Page 3: Dicas para Interfaces Performáticas no seu App Android
Page 4: Dicas para Interfaces Performáticas no seu App Android

INTERAÇÕES COM A UISonho 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...

Page 5: Dicas para Interfaces Performáticas no seu App Android

COMO PERDER FPSs UI Thread pausada na hora da interação

UI Thread está executando alguma operação (lenta) no momento da interação

Page 6: Dicas para Interfaces Performáticas no seu App Android

GARBAGE COLLECTIONPOR QUÊ ELE IMPORTA

Page 7: Dicas para Interfaces Performáticas no seu App Android

GARBAGE COLLECTIONAndroid 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

Page 8: Dicas para Interfaces Performáticas no seu App Android
Page 9: Dicas para Interfaces Performáticas no seu App Android

NÃO GERE LIXO DESNECESSÁRIO

Page 10: Dicas para Interfaces Performáticas no seu App Android

AUTO BOXING Map<Integer, String> map = new HashMap<Integer, String>(); map.put(1024, "Android"); map.put(2048, "performance"); map.put(5096, "matters"); List<Double> values = new ArrayList<Double>(); values.add(3.1415);

Page 11: Dicas para Interfaces Performáticas no seu App Android

map.put(1024, "Android");

new Integer(1024);

Page 12: Dicas para Interfaces Performáticas no seu App Android

SPARSE ARRAYS

SparseArray<String> sparseArray = new SparseArray<String>(); sparseArray.put(665, "Android"); sparseArray.put(666, "rocks");

Page 13: Dicas para Interfaces Performáticas no seu App Android

STRINGS String facebookAvatarURL =

"http://graph.facebook.com/" + facebookID + "/picture?type=large";

String numberStr = "" + number;

DON’T

Page 14: Dicas para Interfaces Performáticas no seu App Android

STRINGS String facebookAvatarURL =

"http://graph.facebook.com/" + facebookID + "/picture?type=large";

....

String numberStr = "" + number;

new StringBuilder();

Page 15: Dicas para Interfaces Performáticas no seu App Android

SEMPRE ÓTIMO ??? StringBuilder builder = new StringBuilder(); for (int i = 0; i < count; i++) { builder.append("ANDROID"); } return builder.toString();

Page 16: Dicas para Interfaces Performáticas no seu App Android

FATOSStringBuilder 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...

Page 17: Dicas para Interfaces Performáticas no seu App Android

BOAS PRÁTICAS final String androidRocks = "android" + "rocks";

// Constantes serão otimizadas pelo compilador // 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

Page 18: Dicas para Interfaces Performáticas no seu App Android

ARRAY LISTS @Override public void onCompleted(List<GraphUser> users, Response response) {

List<FacebookFriend> friends = new ArrayList<FacebookFriend>();

if (users != null) { for (GraphUser user : users) { FacebookFriend friend = new FacebookFriend(user);

friends.add(friend) }

mAdapter = new FriendsAdapter(this, friends); mFriendsList.setAdapter(mAdapter); } }

Page 19: Dicas para Interfaces Performáticas no seu App Android

FATOSArrayList, HashMaps, TreeMaps trabalham sobre Object[], uma estrutura imutável

Se o tamanho pré-definido da Collection estoura, arrays subjacentes serão substituídos por novas instâncias

Page 20: Dicas para Interfaces Performáticas no seu App Android

BOAS PRÁTICASDIMENSIONE o tamanho das suas listas

EVITE adicionar elementos em uma posição específica da lista

List<FacebookFriend> friends = new ArrayList<FacebookFriend>(500);

friends.add(10,friend);

Page 21: Dicas para Interfaces Performáticas no seu App Android

ABSTRAÇÕES EM EXCESSO ...

Page 22: Dicas para Interfaces Performáticas no seu App Android

REUSAR SEMPREQUE POSSÍVEL

Page 23: Dicas para Interfaces Performáticas no seu App Android

OBJECT POOL

Reusar instâncias de objetos ao invés de criar e destruir com (muita!) frequência

http://en.wikipedia.org/wiki/Object_pool_pattern

Page 24: Dicas para Interfaces Performáticas no seu App Android

public class BlocksEngine extends CCLayer {

public void blocksEngine(float dt) { 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

Page 25: Dicas para Interfaces Performáticas no seu App Android

public static final Random sRANDOM = new Random(); public class BlocksEngine extends CCLayer {

public void blocksEngine(float dt) { if (sRANDOM.nextInt(300) == 0) { final Block b = BlocksPool.acquire(); // configurar seu bloco getDelegate().createBlock(b); } } }

Random agora é constante

Reuse um bloco previamente existente !!!

Page 26: Dicas para Interfaces Performáticas no seu App Android

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

Page 27: Dicas para Interfaces Performáticas no seu App Android

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

Page 28: Dicas para Interfaces Performáticas no seu App Android

ADAPTERS @Override public View getView(int position, View convertView, ViewGroup parent) {

final View cellView = mInflater.inflate(R.layout.list_item, parent, false);

final MovieInfo i = getItem(position);

((TextView) cellView.findViewById(R.id.title)).setText(i.getTitle()); ((TextView) cellView.findViewById(R.id.subtitle)).setText(i.getSubs()); return cellView; } DO

N’T

Page 29: Dicas para Interfaces Performáticas no seu App Android

@Override public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null) { convertView = mInflater.inflate(R.layout.list_item, parent, false);

} final MovieInfo i = getItem(position);

((TextView) convertView.findViewById(R.id.title)) .setText(i.getTitle());

((TextView)convertView.findViewById(R.id.subtitle)) .setText(i.getSubs()); return convertView; }

Reusa uma View já criada se possível !

Page 30: Dicas para Interfaces Performáticas no seu App Android

E PARA ESSE TIPO DE LISTA ????

Page 31: Dicas para Interfaces Performáticas no seu App Android

EXECUÇÃO ÓTIMACODIFIQUE PARA A PERFORMANCE

Page 32: Dicas para Interfaces Performáticas no seu App Android

FOR LOOP List<FacebookFriend> friends = new ArrayList<FacebookFriend>();

if (users != null) { for (GraphUser user : users) { FacebookFriend friend = new FacebookFriend(user); friends.add(friend) } }

Otimizada pelo compilador !!!

Page 33: Dicas para Interfaces Performáticas no seu App Android

PARCELLABLE E SERIALIZABLE

http://www.developerphil.com/parcelable-vs-serializable/

Page 34: Dicas para Interfaces Performáticas no seu App Android

PARCELLABLE E SERIALIZABLESerializable é muito mais fácil de implementarParcellable é muito mais eficiente na prática

Serializable para um objetoParcellable para coleções de objetos

Page 35: Dicas para Interfaces Performáticas no seu App Android

CACHE DE OPERAÇÕESstatic class ViewHolder {

public TextView friendName; public TextView friendStatus; public ImageView friendImage; }

Cachear a posição das Views na hierarquia de Views da linha !

Page 36: Dicas para Interfaces Performáticas no seu App Android

public abstract class FasterArrayAdapter<T> extends ArrayAdapter<T> {

@Override public View getView(int position, View convertView, ViewGroup parent) {

Object viewHolder = null;

if (convertView == null) {

viewHolder = new ViewHolder(); convertView = mInflater.inflate(layoutResourceForItem(), parent, false); setupHolder(convertView, viewHolder); convertView.setTag(viewHolder);

} else { viewHolder = convertView.getTag(); }

fillHolder(viewHolder, position); return convertView; } }

Page 37: Dicas para Interfaces Performáticas no seu App Android

public abstract class FasterArrayAdapter<T> extends ArrayAdapter<T> {

@Override public View getView(int position, View convertView, ViewGroup parent) {

Object viewHolder = null;

if (convertView == null) { convertView = mInflater.inflate(layoutResourceForItem(), parent, false);

viewHolder = new ViewHolder(); setupHolder(convertView, viewHolder); convertView.setTag(viewHolder);

} else { viewHolder = convertView.getTag(); }

fillHolder(viewHolder, position); return convertView; } }

Recupera o cache

Calcula posições e faz cache

Preenche seu item

Page 38: Dicas para Interfaces Performáticas no seu App Android

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

Page 39: Dicas para Interfaces Performáticas no seu App Android

MULTITHREADINGHARD WORK FORA DA UI THREAD

Page 40: Dicas para Interfaces Performáticas no seu App Android
Page 41: Dicas para Interfaces Performáticas no seu App Android

JAVA THREADSUSE CASO TENHA CERTEZA ABSOLUTA DO QUE ESTÁ FAZENDO !!Se o item anterior for cumprido, então priorize a UI Thread

Page 42: Dicas para Interfaces Performáticas no seu App Android

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

Page 43: Dicas para Interfaces Performáticas no seu App Android

ASYNCTASK private class DownloadFilesTask extends AsyncTask<URL, Void , Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); } return totalSize; }

protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }

Page 44: Dicas para Interfaces Performáticas no seu App Android

PROBLEMAS COM ASYNCTASKComportamento é inconsistente ao longo das versões de API do Android

Difícil para cancelar tarefas já executando em background ...

Page 45: Dicas para Interfaces Performáticas no seu App Android

USANDO ASYNCTASKAssegure-se de que tarefas serão executadas em paralelo (backporting API14+)

Recomendada para tarefas curtas (segundos)

Cuidados ao declarar como inner class ou ao associar callbacks após a execução

Page 46: Dicas para Interfaces Performáticas no seu App Android

INTENT SERVICEService com uma Thread Worker

MUITO BOM para executar tarefas únicas

Finaliza sozinho após o trabalho executado

Callback mais burocrático após tarefa executada (BroadcastReceiver)

Page 47: Dicas para Interfaces Performáticas no seu App Android

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);

Page 48: Dicas para Interfaces Performáticas no seu App Android

LAYOUTSVOCÊ JÁ OTIMIZOU O SEU HOJE?

Page 49: Dicas para Interfaces Performáticas no seu App Android

HIERARQUIA DE VIEWS

A Crazy TitleA simple subtitle

Nested Linear Layout

Relative Layout

Page 50: Dicas para Interfaces Performáticas no seu App Android

PROCESSAMENTO DE LAYOUTSMais lento conforme

Profundidade da hierarquia de ViewsQuantidade de Views por hierarquia

Profilling via delay nos métodos onMeasure( ), onLayout( ), onDraw( )

Page 51: Dicas para Interfaces Performáticas no seu App Android

OTIMIZAÇÕES EM LAYOUTSPelo menos dois pontos básicos

Conversão de declarações em XML em hierarquias Recuperação de itens dentro de uma hierarquia

NA PRÁTICA Precisamos de hierarquias mais leves e planas !!!

Page 52: Dicas para Interfaces Performáticas no seu App Android

FLATTENING

GRID LAYOUTRELATIVE LAYOUT

COMPOUND DRAWABLES

Page 53: Dicas para Interfaces Performáticas no seu App Android

LAZY LOADING DE VIEWS ...

<ViewStub android:id="@+id/stub" android:layout_width="fill_parent" android:layout_height="fill_parent" android:inflatedId="@+id/inflatedLayout" android:layout="@layout/lazy_layout" />

View inflated = ((ViewStub) findViewById(R.id.stub)).inflate();

Page 54: Dicas para Interfaces Performáticas no seu App Android

IMAGENSSão redimensionados em tempo de execução

SEMPRE FORNEÇA TODOS OS CONJUNTOS DE IMAGENS

Para imagens obtidas via IO, procure cachear os Bitmaps já processados

Page 55: Dicas para Interfaces Performáticas no seu App Android

CONCLUSÕESA HORA DE PRESTAR ATENÇÃO !!!

Page 56: Dicas para Interfaces Performáticas no seu App Android

A EXPERIÊNCIA COM A UI CAI

UM FPS POR VEZ

Page 57: Dicas para Interfaces Performáticas no seu App Android

NÃO GERE LIXO DESNECESSÁRIO

Page 58: Dicas para Interfaces Performáticas no seu App Android

REUSE SEMPRE QUE POSSÍVEL

Page 59: Dicas para Interfaces Performáticas no seu App Android

CODIFIQUE PARA O DESEMPENHO

Page 60: Dicas para Interfaces Performáticas no seu App Android

HARD WORK FORADA UI THREAD

Page 61: Dicas para Interfaces Performáticas no seu App Android

OTIMIZE SEUS LAYOUTS

Page 62: Dicas para Interfaces Performáticas no seu App Android

“DON T̀ AIM CORRECT, AIM FOR AWESOME”

Lucas Rocha, Firefox for Android

Page 63: Dicas para Interfaces Performáticas no seu App Android

ANDROID DEVELOPER

@ubiratanfsoares

gplus.to/ubiratanfsoares

ubiratansoares.com.br/blog