50
rotina androidiana

Mobileconf dicas-android

Embed Size (px)

DESCRIPTION

Apresentação feita durante o mobileconf.

Citation preview

Page 1: Mobileconf dicas-android

5 dicas úteis e práticas para a

rotina androidiana

Page 2: Mobileconf dicas-android

Alberto Souza

•@alberto_souza

•github.com/asouza

Page 3: Mobileconf dicas-android

Parsear json

•Implementação padrão do Android(org.json)

•GSON

•Outros zilhões

Page 4: Mobileconf dicas-android

JSON-JavaArrayList<Imovel> imoveis = new ArrayList<Imovel>();

try {

JSONObject imoveisComTotal = new JSONObject(imoveisJSON);

JSONArray jsonArrayDeImoveis = imoveisComTotal

.getJSONArray("imoveis");

for (int i = 0; i < jsonArrayDeImoveis.length(); i++) {

JSONObject jsonObjectDoImovel = new JSONObject(

jsonArrayDeImoveis.getJSONObject(i).toString());

JSONObject jsonImovel = new JSONObject(

jsonObjectDoImovel.getString("imovel"));

Imovel imovel = criaImovelEmFuncaoDo(jsonImovel);

JSONObject jsonImobilaria = jsonImovel

.getJSONObject("imobiliaria");

imovel.setImobiliaria(criaImobiliariaEmFuncaoDo(jsonImobilaria));

Page 5: Mobileconf dicas-android

Braçal

•Deu trabalho então me entregue uma vantagem

Page 6: Mobileconf dicas-android

GSON

private final static Gson gson = new Gson();

gson.toJson(serializable);

Page 7: Mobileconf dicas-android

Justo

•Suporta as situações mais comuns

•Mas ainda achei meio lento

•Tem que ter o modelo compatível

Page 9: Mobileconf dicas-android

JACKSON

ObjectMapper mapper = new ObjectMapper();

TodosImoveis todosImoveis = mapper.readValue(imoveisJSON,TodosImoveis.class);

Page 10: Mobileconf dicas-android

Simples também

•Suporta as situações mais comuns

•Mais fléxivel em relação ao mapeamento, atributo ou getter/setter

•Realmente foi mais rápido.

Page 11: Mobileconf dicas-android

Fallback esperto

@JsonAnySetter

public void handleUnknown(String key, Object value) {

if (key.equals("fallback_url")) {

this.linkOriginal = value.toString();

}

}

Page 12: Mobileconf dicas-android

Modo hardtry{

JsonFactory f = new JsonFactory();

JsonGenerator g = f.createJsonGenerator(new StringWriter());

g.writeStartObject();

g.writeObjectFieldStart("imovel");

g.writeStringField("titulo","Casa de praia em salvador");

g.writeStringField("descricao", "Joe");

g.writeEndObject(); // for field 'name'

g.close(); // important: will force flushing of output, close underlying output stream

}

catch(Exception e ){//catch vazio, ninguém viu}

Page 13: Mobileconf dicas-android

Supostas vantagens

•Bem mais rápido

•Tem que ler na ordem dos campos do json

•Tudo braçal

Page 14: Mobileconf dicas-android

Ainda integrando

•Como fazer os requests?

Page 15: Mobileconf dicas-android

AsyncTask

•Faz só o básico

Page 16: Mobileconf dicas-android

Problemas

•Tentativa de conexão não deu certo

Page 17: Mobileconf dicas-android

Vai perder fácil?

Page 18: Mobileconf dicas-android

Problemas

•Pedir a resposta gzipada?

Page 19: Mobileconf dicas-android

Problemas

•Tempo máximo de espera

Page 20: Mobileconf dicas-android

Deixar esperando

Page 21: Mobileconf dicas-android

Feedbacktry {

new BuscaProximos(proximosFragment)

.buscaAPagina(calculaPaginaAtual());

} catch (LocationProvidersOffException e) {

new GPSAlert(proximosFragment).show();

}

Page 22: Mobileconf dicas-android

Loopj Android Async Task

•Configurações prontas

Page 23: Mobileconf dicas-android

CódigoConnManagerParams.setTimeout(httpParams, socketTimeout);

ConnManagerParams.setMaxConnectionsPerRoute(httpParams, new ConnPerRouteBean(maxConnections));

ConnManagerParams.setMaxTotalConnections(httpParams, DEFAULT_MAX_CONNECTIONS);

HttpConnectionParams.setSoTimeout(httpParams, socketTimeout);

HttpConnectionParams.setConnectionTimeout(httpParams, socketTimeout);

HttpConnectionParams.setTcpNoDelay(httpParams, true);

HttpConnectionParams.setSocketBufferSize(httpParams, DEFAULT_SOCKET_BUFFER_SIZE);

HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);

HttpProtocolParams.setUserAgent(httpParams, String.format("android-async-http/%s (http://loopj.com/android-async-http)", VERSION));

SchemeRegistry schemeRegistry = new SchemeRegistry();

schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(httpParams, schemeRegistry);

httpContext = new SyncBasicHttpContext(new BasicHttpContext());

httpClient = new DefaultHttpClient(cm, httpParams);

httpClient.addRequestInterceptor(new HttpRequestInterceptor() {

@Override

public void process(HttpRequest request, HttpContext context) {

if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {

request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);

}

for (String header : clientHeaderMap.keySet()) {

request.addHeader(header, clientHeaderMap.get(header));

}

}

});

Page 24: Mobileconf dicas-android

Loopj Android Async Task

•Retry pronto

•Tempo máximo configurado

•GZIP

•Handler para binário

Page 25: Mobileconf dicas-android

Simples de usar

AsyncHttpClient client = new AsyncHttpClient();

client.get(url,tratadorDoRetorno);

Page 26: Mobileconf dicas-android

Handler padrão

DefaultRequestHandler<TodosImoveis> imoveisEncontradosHandler = new DefaultRequestHandler<TodosImoveis>() {

@Override

public void onSucess(TodosImoveis result) {

BuscaPeloFiltroTask.this.onPostExecute(result);

}

//onError...

Page 27: Mobileconf dicas-android

Já fiz com Async Task do android

public void execute(Integer... params) {

enganaOCaraEUsaOutraLib(params);

}

Page 28: Mobileconf dicas-android

Customizando

AsyncHttpClient client = new AsyncHttpClient();

DefaultHttpClient defaultClient = (DefaultHttpClient) client.getHttpClient();

HttpRequestRetryHandler retryHandler = defaultClient.getHttpRequestRetryHandler();

client.get(url,handler);

Page 29: Mobileconf dicas-android

Um pouco de performance

•Carregar imagens por exemplo

Page 30: Mobileconf dicas-android

Cache

•Tamanho do cache

Page 31: Mobileconf dicas-android

Problemas

•Expiração

•Memória

•Tamanho

Page 32: Mobileconf dicas-android

Baseado no aparelho

•Cache pronto para usar nas apps android

Page 33: Mobileconf dicas-android

LRUCache

final int memClass = ((ActivityManager) this

.getSystemService(Context.ACTIVITY_SERVICE)).getMemoryClass();

int memoryInBytes = 1024 * 1024 * memClass;

final int cacheSize = memoryInBytes / 8;

cache = new LruCache<String,Bitmap>(maxSize);

Page 34: Mobileconf dicas-android

Tamanho das entradas do cache

•Como fazemos?

Page 35: Mobileconf dicas-android

Mudamos o comportamento

cache = new LruCache<String,Bitmap>(maxSize) {

protected int sizeOf(String key, Bitmap bitmap) {

return bitmap.getByteCount();

};

};

Page 36: Mobileconf dicas-android

Pontos lentos

•Como descobrir?

Page 37: Mobileconf dicas-android

App que consome serviço

•Vai olhar o serviço

Page 38: Mobileconf dicas-android

Profile

•Vamos chorar

Page 39: Mobileconf dicas-android

StrictMode

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()

.detectDiskReads()

.detectDiskWrites()

.detectNetwork()

.penaltyLog()

.build());

StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()

.detectLeakedSqlLiteObjects()

.detectLeakedClosableObjects()

.penaltyLog()

.build());

Page 40: Mobileconf dicas-android

Reclamação

04-05 11:07:54.598: E/StrictMode(6032): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.

04-05 11:07:54.598: E/StrictMode(6032): java.lang.Throwable: Explicit termination method 'close' not called

04-05 11:07:54.598: E/StrictMode(6032): at dalvik.system.CloseGuard.open(CloseGuard.java:184)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.CursorWindow.<init>(CursorWindow.java:137)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.CursorWindow.<init>(CursorWindow.java:41)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.CursorWindow$1.createFromParcel(CursorWindow.java:689)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.CursorWindow$1.createFromParcel(CursorWindow.java:687)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.CursorWindow.newFromParcel(CursorWindow.java:698)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.BulkCursorProxy.getWindow(BulkCursorNative.java:196)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.BulkCursorToCursorAdaptor.onMove(BulkCursorToCursorAdaptor.java:94)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:178)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.AbstractCursor.moveToFirst(AbstractCursor.java:201)

04-05 11:07:54.598: E/StrictMode(6032): at android.database.CursorWrapper.moveToFirst(CursorWrapper.java:65)

04-05 11:07:54.598: E/StrictMode(6032): at android_maps_conflict_avoidance.com.google.common.android.AndroidConfig.getSetting(AndroidConfig.java:219)

04-05 11:07:54.598: E/StrictMode(6032): at android_maps_conflict_avoidance.com.google.common.android.AndroidConfig.getDistributionChannelInternal(AndroidConfig.java:197)

04-05 11:07:54.598: E/StrictMode(6032): at android_maps_conflict_avoidance.com.google.common.Config.init(Config.java:273)

04-05 11:07:54.598: E/StrictMode(6032): at android_maps_conflict_avoidance.com.google.common.android.AndroidConfig.<init>(AndroidConfig.java:100)

04-05 11:07:54.598: E/StrictMode(6032): at android_maps_conflict_avoidance.com.google.common.android.AndroidConfig.<init>(AndroidConfig.java:87)

04-05 11:07:54.598: E/StrictMode(6032): at com.google.android.maps.MapActivity.onCreate(MapActivity.java:419)

04-05 11:07:54.598: E/StrictMode(6032): at android.support.v4.app.FragmentActivity.onCreate(Unknown Source)

04-05 11:07:54.598: E/StrictMode(6032): at br.com.homehunter.infra.UseStorageFragmentActivity.onCreate(UseStorageFragmentActivity.java:14)

04-05 11:07:54.598: E/StrictMode(6032): at br.com.homehunter.MainActivity.onCreate(MainActivity.java:28)

04-05 11:07:54.598: E/StrictMode(6032): at android.app.Activity.performCreate(Activity.java:4465)

04-05 11:07:54.598: E/StrictMode(6032): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)

04-05 11:07:54.598: E/StrictMode(6032): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)

04-05 11:07:54.598: E/StrictMode(6032): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)

04-05 11:07:54.598: E/StrictMode(6032): at android.app.ActivityThread.access$600(ActivityThread.java:123)

04-05 11:07:54.598: E/StrictMode(6032): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)

04-05 11:07:54.598: E/StrictMode(6032): at android.os.Handler.dispatchMessage(Handler.java:99)

04-05 11:07:54.598: E/StrictMode(6032): at android.os.Looper.loop(Looper.java:137)

04-05 11:07:54.598: E/StrictMode(6032): at android.app.ActivityThread.main(ActivityThread.java:4424)

04-05 11:07:54.598: E/StrictMode(6032): at java.lang.reflect.Method.invokeNative(Native Method)

04-05 11:07:54.598: E/StrictMode(6032): at java.lang.reflect.Method.invoke(Method.java:511)

04-05 11:07:54.598: E/StrictMode(6032): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)

04-05 11:07:54.598: E/StrictMode(6032): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)

04-05 11:07:54.598: E/StrictMode(6032): at dalvik.system.NativeStart.main(Native Method)

Page 41: Mobileconf dicas-android

Mais profile

•Traceview

Page 42: Mobileconf dicas-android

Marca os pontos

public void buscaAPagina(int pagina) throws LocationProvidersOffException{

Debug.startMethodTracing("buscaPagina");

//possivel código ruim aqui

Debug.stopMethodTracing();

}

Page 43: Mobileconf dicas-android

Busca o arquivo

./adb pull /sdcard/buscaPagina.trace /tmp

./traceview /tmp/buscaPagina

Page 44: Mobileconf dicas-android

Agora vai caçar

Page 45: Mobileconf dicas-android

Comandos para o emulador

•DDMS/Emulator control

Page 46: Mobileconf dicas-android

Mas...

•Já tentou controlar a bateria?

•E quando subiu o emulador com o tamanho errado

Page 47: Mobileconf dicas-android

Chique

•Conectar no emulador via telnet

Page 48: Mobileconf dicas-android

Comando

Page 49: Mobileconf dicas-android

Alterando algumas coisas a mais

power capacity 20

window scale 0.5

Page 50: Mobileconf dicas-android

Valeu!@alberto_souza

github.com/asouza