Mobileconf dicas-android

Preview:

DESCRIPTION

Apresentação feita durante o mobileconf.

Citation preview

5 dicas úteis e práticas para a

rotina androidiana

Alberto Souza

•@alberto_souza

•github.com/asouza

Parsear json

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

•GSON

•Outros zilhões

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

Braçal

•Deu trabalho então me entregue uma vantagem

GSON

private final static Gson gson = new Gson();

gson.toJson(serializable);

Justo

•Suporta as situações mais comuns

•Mas ainda achei meio lento

•Tem que ter o modelo compatível

JACKSON

ObjectMapper mapper = new ObjectMapper();

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

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.

Fallback esperto

@JsonAnySetter

public void handleUnknown(String key, Object value) {

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

this.linkOriginal = value.toString();

}

}

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}

Supostas vantagens

•Bem mais rápido

•Tem que ler na ordem dos campos do json

•Tudo braçal

Ainda integrando

•Como fazer os requests?

AsyncTask

•Faz só o básico

Problemas

•Tentativa de conexão não deu certo

Vai perder fácil?

Problemas

•Pedir a resposta gzipada?

Problemas

•Tempo máximo de espera

Deixar esperando

Feedbacktry {

new BuscaProximos(proximosFragment)

.buscaAPagina(calculaPaginaAtual());

} catch (LocationProvidersOffException e) {

new GPSAlert(proximosFragment).show();

}

Loopj Android Async Task

•Configurações prontas

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

}

}

});

Loopj Android Async Task

•Retry pronto

•Tempo máximo configurado

•GZIP

•Handler para binário

Simples de usar

AsyncHttpClient client = new AsyncHttpClient();

client.get(url,tratadorDoRetorno);

Handler padrão

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

@Override

public void onSucess(TodosImoveis result) {

BuscaPeloFiltroTask.this.onPostExecute(result);

}

//onError...

Já fiz com Async Task do android

public void execute(Integer... params) {

enganaOCaraEUsaOutraLib(params);

}

Customizando

AsyncHttpClient client = new AsyncHttpClient();

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

HttpRequestRetryHandler retryHandler = defaultClient.getHttpRequestRetryHandler();

client.get(url,handler);

Um pouco de performance

•Carregar imagens por exemplo

Cache

•Tamanho do cache

Problemas

•Expiração

•Memória

•Tamanho

Baseado no aparelho

•Cache pronto para usar nas apps 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);

Tamanho das entradas do cache

•Como fazemos?

Mudamos o comportamento

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

protected int sizeOf(String key, Bitmap bitmap) {

return bitmap.getByteCount();

};

};

Pontos lentos

•Como descobrir?

App que consome serviço

•Vai olhar o serviço

Profile

•Vamos chorar

StrictMode

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

.detectDiskReads()

.detectDiskWrites()

.detectNetwork()

.penaltyLog()

.build());

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

.detectLeakedSqlLiteObjects()

.detectLeakedClosableObjects()

.penaltyLog()

.build());

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)

Mais profile

•Traceview

Marca os pontos

public void buscaAPagina(int pagina) throws LocationProvidersOffException{

Debug.startMethodTracing("buscaPagina");

//possivel código ruim aqui

Debug.stopMethodTracing();

}

Busca o arquivo

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

./traceview /tmp/buscaPagina

Agora vai caçar

Comandos para o emulador

•DDMS/Emulator control

Mas...

•Já tentou controlar a bateria?

•E quando subiu o emulador com o tamanho errado

Chique

•Conectar no emulador via telnet

Comando

Alterando algumas coisas a mais

power capacity 20

window scale 0.5

Valeu!@alberto_souza

github.com/asouza

Recommended