Flatbuffers em Android

Dando sequência a série de posts sobre serialização de dados com FlatBuffers, vamos falar sobre o uso de FlatBuffers na plataforma Android. Seguiremos basicamente os mesmos passos feitos no post sobre a utilização de FlatBuffers em apps universais – criação do projeto, geração de classes através do compilador de FlatBuffers, criação das classes para parsing do arquivo JSON, montagem de uma tela simples para a exibição dos dados, programação do código para carregamento dos dados e comparação dos tempos de carregamento – e claro, verificar se o ganho de performance em relação ao uso de conteúdo JSON também se repete no Android.

Caso queira seguir passo a passo a implementação feita neste post, baixe os seguintes arquivos, disponibilizados no primeiro post sobre o tema: o arquivo de esquema de FlatBuffer (imoveis.fbs), o arquivo JSON que contém os dados que serão importados pela aplicação (imoveis.json) e o compilador de FlatBuffers (flatc.exe).

Como de costume, todo o código da demonstração está disponível no repositório GitHub do talkitbr.

Criação do projeto

Desta vez utilizaremos o Android Studio para criar o projeto, bem como o SDK 23 do Android. Vamos começar então!

Abra o Android Studio e clique em Start a new Android Studio project.

flatbuffers_android (1)

Depois, nomeie a aplicação como FlatBuffersAndroid e use talkitbr.com como Company Domain. Escolha um caminho de sua preferência para salvar o projeto e em seguida clique no botão Next.

flatbuffers_android (2)

Continuando, mantenha marcada apenas a opção Phone and Tablet. Selecione a opção API 14: Android 4.0 (IceCreamSandwich) na caixa de seleção Minimum SDK. Clique no botão Next.

flatbuffers_android (3)

Como faremos uma aplicação muito simples, selecione a opção Empty Activity na tela de adição de activities e em seguida clique no botão Next.

flatbuffers_android (4)

Mantenha os valores dos campos Activity Name e Layout Name e deixe marcada a opção Generate Layout File. Clique no botão Finish.

flatbuffers_android (5)

Assim como fizemos na aplicação universal, não utilizaremos o parser JSON nativo da plataforma – iremos utilizar um framework de terceiros que apresenta melhor desempenho para esta tarefa. No caso do Android utilizaremos o Jackson, que além de ser rápido, permite usar anotações para definir regras de parsing.

Para adicionar o Jackson como dependência do projeto, abra o arquivo build.gradle do módulo app no painel Project:

flatbuffers_android (6)

Na seção dependencies, coloque como dependência de compilação os seguintes pacotes: com.fasterxml.jackson.core:jackson-core:2.4.6com.fasterxml.jackson.core:jackson-annotations:2.4.6com.fasterxml.jackson.core:jackson-databind:2.4.6:

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  testCompile 'junit:junit:4.12'
  compile 'com.android.support:appcompat-v7:23.1.1'

  compile 'com.fasterxml.jackson.core:jackson-core:2.4.6'
  compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.6'
  compile 'com.fasterxml.jackson.core:jackson-databind:2.4.6'
}

Para evitar a duplicidade de arquivos presentes nos pacotes do Jackson durante a criação do arquivo APK, declare a exclusão dos arquivos META-INF/NOTICE e META-INF/LICENSE. Isso deve ser feito na subseção packagingOptions da seção android:

android {
 ...

  packagingOptions {
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/LICENSE'
  }
}

Ao final, o arquivo build.gradle deve estar parecido com isso:

apply plugin: 'com.android.application'

android {
  compileSdkVersion 23
  buildToolsVersion "23.0.2"

  defaultConfig {
    applicationId "com.talkitbr.flatbuffersandroid"
    minSdkVersion 14
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
  }

  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }

  packagingOptions {
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/LICENSE'
  }
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  testCompile 'junit:junit:4.12'
  compile 'com.android.support:appcompat-v7:23.1.1'

  compile 'com.fasterxml.jackson.core:jackson-core:2.4.6'
  compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.6'
  compile 'com.fasterxml.jackson.core:jackson-databind:2.4.6'
}

Novamente será necessário copiar os arquivos de suporte para a leitura de FlatBuffers do repositório do projeto FlatBuffers. Copie a pasta com que está dentro da pasta java do repositório e cole-a na pasta java de nosso projeto recém criado. Caso seja apresentado o diálogo de seleção do diretório destino, selecione a opção “…\app\src\main\java”:

flatbuffers_android (7)

Ao final da cópia, deveremos ter as classes Constants, FlatBufferBuilder, Struct e Table presentes dentro do pacote com.google.flatbuffers:

flatbuffers_android (8)

Geração das classes de modelo para leitura do FlatBuffer

Novamente iremos alterar o namespace utilizado pelo compilador de FlatBuffers para gerar as classes de manipulação. Abra o arquivo de esquema (imoveis.fbs) e altere o namespace para com.talkitbr.flatbuffersandroid.model.vo.fb:

namespace com.talkitbr.flatbuffersandroid.model.vo.fb;

Após a modificação, abra um prompt de comando, acesse o diretório onde estão localizados o compilador de FlatBuffers e seu arquivo de esquema e execute o compilador com a opção -j para gerar as classes de modelo para Java (ao invés de -n, utilizada para gerar as classes em C#):

flatc -b -j imoveis.fbs imoveis.json

O arquivo de FlatBuffer foi gerado na pasta atual e as classes de manipulação foram criadas na estrutura de diretórios definida pelo namespace:

flatbuffers_android (9)

Copie a pasta com para a pasta java do projeto (caso seja solicitado o diretório destino dos arquivos, selecione …\app\src\main\java):

flatbuffers_android (10)

Criação das classes de modelo para parsing do arquivo JSON

Como dito, iremos utilizar o framework Jackson para o parsing do arquivo JSON e novamente será necessário criar um modelo de classes que represente o arquivo. Não tentaremos utilizar as mesmas classes geradas pelo compilador de FlatBuffers pelo mesmo motivo que não o fizemos no post sobre apps universais.

Nada mudou na estrutura do arquivo JSON, portanto nossa hierarquia de classes continua a mesma:

flatbuffers_universal_windows_pps (8)

Todas as classes ganharam o sufixo “JSON” para diferenciá-las das classes geradas pelo compilador de FlatBuffers. Ao criá-las, salve-as no pacote com.talkitbr.flatbuffersandroid.model.vo.json.

Enumeradores

Temos dois enumeradores em nosso modelo de dados: um para os estados da federação e outro para identificar o tipo de negociação do imóvel (compra ou aluguel). Ambas informações são dadas como strings no arquivo JSON e o parser precisa saber converter esse texto para um dos valores do enumerador. Para isso, utilizaremos uma anotação para indicar ao parser qual método é responsável por essa conversão.

A anotação JsonCreator deve ser utilizada em um método estático definido no enumerador, que deve ter como parâmetro um string e deve retornar um dos valores do enumerador (ou null caso não seja possível realizar a conversão):

@JsonCreator
public static EstadoJSON fromString(String estadoStr) {
    EstadoJSON estado = null;
    EstadoJSON[] estados = EstadoJSON.values();

    for (int i = 0; (i < estados.length) && (estado == null); i++) {
        if (estados[i].name().equals(estadoStr)) {
            estado = estados[i];
        }
    }

    return estado;
}

EstadoJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

import com.fasterxml.jackson.annotation.JsonCreator;

public enum EstadoJSON {
    AC, AL, AP, AM, BA, CE, DF, ES, GO, MA, MT, MS, MG, PA, PB, PR, PE, PI, RJ, RN, RS, RO, RR, SC, SP, SE, TO;

    @JsonCreator
    public static EstadoJSON fromString(String estadoStr) {
        EstadoJSON estado = null;
        EstadoJSON[] estados = EstadoJSON.values();

        for (int i = 0; (i < estados.length) && (estado == null); i++) {
            if (estados[i].name().equals(estadoStr)) {
                estado = estados[i];
            }
        }

        return estado;
    }
}

TipoJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

import com.fasterxml.jackson.annotation.JsonCreator;

public enum TipoJSON {
    COMPRA("compra"), ALUGUEL("aluguel");

    private final String tipoStr;

    TipoJSON(String tipoStr) {
        this.tipoStr = tipoStr;
    }

    @JsonCreator
    public static TipoJSON fromString(String tipoStr) {
        TipoJSON tipo = null;
        TipoJSON[] tipos = TipoJSON.values();

        for (int i = 0; (i < tipos.length) && (tipo == null); i++) {
            if (tipos[i].tipoStr.equals(tipoStr)) {
                tipo = tipos[i];
            }
        }

        return tipo;
    }
}

Classes

Como as propriedades de nossas classes correspondem aos nomes das chaves do arquivo JSON, não é necessário utilizar nenhuma anotação para fazer a correspondência. Porém, como um imóvel pode ser vendido tanto por um corretor quanto por uma imobiliária, precisamos informar ao parser qual o tipo do vendedor do imóvel. Isso é feito através da anotação JsonTypeInfo, que deve ser colocada na classe abstrata do vendedor:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "classVendedor")

Esta anotação indica que quando o parser se deparar com a classe abstrata que o declara ele precisará ler a chave classVendedor para descobrir qual é a classe concreta a ser utilizada.

AreaJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

public class AreaJSON {
    private float largura;
    private float comprimento;

    public float getLargura() {
        return largura;
    }

    public void setLargura(float largura) {
        this.largura = largura;
    }

    public float getComprimento() {
        return comprimento;
    }

    public void setComprimento(float comprimento) {
        this.comprimento = comprimento;
    }
}

VendedorJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "classVendedor")
public abstract class VendedorJSON {
    private String nome;
    private String telefone;

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getTelefone() {
        return telefone;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }
}

ImobiliariaJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

public class ImobiliariaJSON extends VendedorJSON {
    private String endereco;
    private int numero;
    private String bairro;
    private String cidade;
    private EstadoJSON estado;

    public String getEndereco() {
        return endereco;
    }

    public void setEndereco(String endereco) {
        this.endereco = endereco;
    }

    public int getNumero() {
        return numero;
    }

    public void setNumero(int numero) {
        this.numero = numero;
    }

    public String getBairro() {
        return bairro;
    }

    public void setBairro(String bairro) {
        this.bairro = bairro;
    }

    public String getCidade() {
        return cidade;
    }

    public void setCidade(String cidade) {
        this.cidade = cidade;
    }

    public EstadoJSON getEstado() {
        return estado;
    }

    public void setEstado(EstadoJSON estado) {
        this.estado = estado;
    }
}

CorretorJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

public class CorretorJSON extends VendedorJSON {
    private String creci;

    public String getCreci() {
        return creci;
    }

    public void setCreci(String creci) {
        this.creci = creci;
    }
}

ImovelJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

public abstract class ImovelJSON {
    private String endereco;
    private int numero;
    private String bairro;
    private String cidade;
    private EstadoJSON estado;
    private int quartos;
    private TipoJSON tipo;
    private float valor;
    private boolean aceitaFGTS = true;
    private VendedorJSON vendedor;
    private String urlFoto;

    public String getEndereco() {
        return endereco;
    }

    public void setEndereco(String endereco) {
        this.endereco = endereco;
    }

    public int getNumero() {
        return numero;
    }

    public void setNumero(int numero) {
        this.numero = numero;
    }

    public String getBairro() {
        return bairro;
    }

    public void setBairro(String bairro) {
        this.bairro = bairro;
    }

    public String getCidade() {
        return cidade;
    }

    public void setCidade(String cidade) {
        this.cidade = cidade;
    }

    public EstadoJSON getEstado() {
        return estado;
    }

    public void setEstado(EstadoJSON estado) {
        this.estado = estado;
    }

    public int getQuartos() {
        return quartos;
    }

    public void setQuartos(int quartos) {
        this.quartos = quartos;
    }

    public TipoJSON getTipo() {
        return tipo;
    }

    public void setTipo(TipoJSON tipo) {
        this.tipo = tipo;
    }

    public float getValor() {
        return valor;
    }

    public void setValor(float valor) {
        this.valor = valor;
    }

    public boolean isAceitaFGTS() {
        return aceitaFGTS;
    }

    public void setAceitaFGTS(boolean aceitaFGTS) {
        this.aceitaFGTS = aceitaFGTS;
    }

    public VendedorJSON getVendedor() {
        return vendedor;
    }

    public void setVendedor(VendedorJSON vendedor) {
        this.vendedor = vendedor;
    }

    public String getUrlFoto() {
        return urlFoto;
    }

    public void setUrlFoto(String urlFoto) {
        this.urlFoto = urlFoto;
    }
}

ApartamentoJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

public class ApartamentoJSON extends ImovelJSON {
    private float area;
    private int numApto;

    public float getArea() {
        return area;
    }

    public void setArea(float area) {
        this.area = area;
    }

    public int getNumApto() {
        return numApto;
    }

    public void setNumApto(int numApto) {
        this.numApto = numApto;
    }
}

CasaJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

public class CasaJSON extends ImovelJSON {
    private AreaJSON areaTerreno;
    private float areaConstruida;

    public AreaJSON getAreaTerreno() {
        return areaTerreno;
    }

    public void setAreaTerreno(AreaJSON areaTerreno) {
        this.areaTerreno = areaTerreno;
    }

    public float getAreaConstruida() {
        return areaConstruida;
    }

    public void setAreaConstruida(float areaConstruida) {
        this.areaConstruida = areaConstruida;
    }
}

ImoveisJSON.java

package com.talkitbr.flatbuffersandroid.model.vo.json;

import java.util.List;

public class ImoveisJSON {
    private List<ApartamentoJSON> aptos;
    private List<CasaJSON> casas;

    public List<ApartamentoJSON> getAptos() {
        return aptos;
    }

    public void setAptos(List<ApartamentoJSON> aptos) {
        this.aptos = aptos;
    }

    public List<CasaJSON> getCasas() {
        return casas;
    }

    public void setCasas(List<CasaJSON> casas) {
        this.casas = casas;
    }
}

Agora temos todas as classes de modelo necessárias para a leitura, tanto de FlatBuffers quanto de arquivos JSON:

flatbuffers_android (11)

Arquivos de dados

O intuito deste post é medir a performance da conversão de dados serializados em um modelo de classes carregado na memória. Portanto, iremos embarcar os arquivos de dados na própria aplicação. Para tanto, é necessário criar a pasta de assets do projeto. Clique com o botão direito sobre o módulo app, selecione os itens de menu New, Folder e Assets Folder:

flatbuffers_android (12)

Na tela do assistente de criação da pasta, selecione main no campo Target Source Set e clique em Finish:

flatbuffers_android (13)

Agora copie para a pasta assets os arquivos imoveis.fb (criado durante a geração das classes pelo compilador de FlatBuffers) e imoveis.json (criado no primeiro post sobre FlatBuffers).

Alguns parágrafos atrás dissemos que seria necessário utilizar uma anotação na classe abstrata que representa o vendedor para informar qual classe concreta utilizar – e isso era feito através de uma chave no arquivo JSON, que em nosso caso, a nomeamos como classVendedor. Já fizemos o uso da anotação, agora é hora de modificar o arquivo JSON para incluir esta chave.

Abra o arquivo imoveis.json presente na pasta assets e insira a chave classVendedor para cada um dos blocos de vendedor do arquivo. O valor da chave deve ser o nome completo da classe concreta que representa o vendedor, isto é, o nome do pacote deve ser incluído no nome da classe. Quando o vendedor for um corretor autônomo, utilize a classe com.talkitbr.flatbuffersandroid.model.vo.json.CorretorJSON. No caso de imobiliárias, utilize a classe com.talkitbr.flatbuffersandroid.model.vo.json.ImobiliariaJSON. Exemplo:

{
    "endereco": "Rua C",
    "numero": 110,
    "bairro": "Centro",
    "cidade": "Recife",
    "estado": "PE",
    "areaTerreno": {
        "largura": 20,
        "comprimento": 40
    },
    "areaConstruida": 350,
    "quartos": 7,
    "tipo": "aluguel",
    "valor": 3500,
    "aceitaFGTS": false,
    "vendedor": {
        "classVendedor": "com.talkitbr.flatbuffersandroid.model.vo.json.CorretorJSON",
        "nome": "Maria Beterraba",
        "telefone": "95555-9999",
        "creci": "zz55pw"
    },
    "urlFoto": "http://www.fotosdeimoves.com/casa2.jpg"
}

Remova também as chaves nomeadas como vendedor_type, pois elas eram utilizadas para serializar os dados como FlatBuffers e não serão mais necessárias.

Tela para comparação dos tempos de deserialização

Vamos construir uma tela simples para nos mostrar os tempos de deserialização tanto do FlatBuffer quando do arquivo JSON:

flatbuffers_android (14)

Abra o arquivo activity_main.xml e coloque os seguintes componentes, posicionando-os como estão na imagem acima:

  • Um Button com o id activity_main_load_fb_button e com o texto Carregar FlatBuffer.
  • Um TextView com o id activity_main_fb_loading_time e com o texto “Tempo de carregamento:“.
  • Um Button com o id activity_main_load_json_button e com o texto Carregar JSON.
  • Um TextView com o id activity_main_json_loading_time e com o texto “Tempo de carregamento:“.

O conteúdo do arquivo de layout deve ser semelhante a isso:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.talkitbr.flatbuffersandroid.MainActivity">

    <Button android:id="@+id/activity_main_load_fb_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="Carregar FlatBuffer" />

    <TextView android:id="@+id/activity_main_fb_loading_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/activity_main_load_fb_button" android:layout_centerHorizontal="true" android:text="Tempo de carregamento: " />

    <Button android:id="@+id/activity_main_load_json_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/activity_main_fb_loading_time" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:text="Carregar JSON" />

    <TextView android:id="@+id/activity_main_json_loading_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/activity_main_load_json_button" android:layout_centerHorizontal="true" android:text="Tempo de carregamento: " />
</RelativeLayout>

Código para deserialização dos dados

Agora que criamos o layout da tela principal da aplicação, precisamos definir as ações dos botões. Abra a classe MainActivity e crie dois listeners de clique para os botões de deserialização de dados, um para o FlatBuffer e outro para o arquivo JSON:

private class LoadFlatBufferButtonClickListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
        InputStream is = null;

        try {
            is = getResources().getAssets().open("imoveis.fb");

            byte[] buffer = new byte[1024];
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            int read;

            while ((read = is.read(buffer)) > 0) {
                baos.write(buffer, 0, read);
            }

            ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());

            long start = System.currentTimeMillis();

            Imoveis imoveis = Imoveis.getRootAsImoveis(bb);

            long end = System.currentTimeMillis();

            mFlatBuffersLoadingTime.setText("Tempo de carregamento: " + (end - start) + " milissegundos.");

            Log.d("talkitbr-FB", "Total de apartamentos carregados: " + imoveis.aptosLength() + ", total de casas carregadas: " + imoveis.casasLength());
        } catch (IOException e) {
            Log.e("talkitbr-FB", "Ocorreu um erro ao carregar o FlatBuffer.", e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    // Não faz nada
                }
            }
        }
    }
}
private class LoadJSONButtonClickListener implements View.OnClickListener {
    @Override
    public void onClick(View v) {
        InputStream is = null;

        try {
            is = getResources().getAssets().open("imoveis.json");

            ObjectMapper mapper = new ObjectMapper();

            long start = System.currentTimeMillis();

            ImoveisJSON imoveis = mapper.readValue(is, ImoveisJSON.class);

            long end = System.currentTimeMillis();

            mJSONLoadingTime.setText("Tempo de carregamento: " + (end - start) + " milissegundos.");

            Log.d("talkitbr-JSON", "Total de apartamentos carregados: " + imoveis.getAptos().size() + ", total de casas carregadas: " + imoveis.getCasas().size());
        } catch (IOException e) {
            Log.e("talkitbr-JSON", "Ocorreu um erro ao carregar o arquivo JSON.", e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    // Não faz nada
                }
            }
        }
    }
}

Agora faça a ligação entre os listeners de clique e os botões:

private TextView mFlatBuffersLoadingTime;

private TextView mJSONLoadingTime;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button loadFlatBufferButton = (Button) findViewById(R.id.activity_main_load_fb_button);
    Button loadJSONButton = (Button) findViewById(R.id.activity_main_load_json_button);
    mFlatBuffersLoadingTime = (TextView) findViewById(R.id.activity_main_fb_loading_time);
    mJSONLoadingTime = (TextView) findViewById(R.id.activity_main_json_loading_time);

    loadFlatBufferButton.setOnClickListener(new LoadFlatBufferButtonClickListener());
    loadJSONButton.setOnClickListener(new LoadJSONButtonClickListener());
}

Hora de executar o projeto

O projeto está pronto para execução. Primeiro vamos executá-lo em um emulador da versão 4.4 do Android. E este é o resultado:

flatbuffers_android (15)

O carregamento do FlatBuffer foi praticamente instantâneo, enquanto o carregamento do arquivo JSON levou 250 milissegundos, demasiadamente mais lento.

Agora irei utilizar um telefone low end com Android 4.1.2 para executar a aplicação:

flatbuffers_android (16)

Novamente o carregamento do FlatBuffer foi praticamente instantâneo, marcando 1 milissegundo. Já no caso do carregamento do arquivo JSON, o telefone foi um pouco mais rápido que o emulador.

Caso não tenha feito o tutorial passo a passo, obtenha o código fonte no repositório GitHub do talkitbr.

Considerações finais

Novamente o uso de FlatBuffers se mostrou mais eficiente que o uso de JSON para a serialização de dados. Vimos que mesmo em um dispositivo com hardware mais modesto a deserialização é feita de forma rápida.

O objetivo dessa série de posts sobre FlatBuffers era mostrar que a aposta do Facebook neste modo de serialização tinha sentido e que os ganhos para quem o adota são enormes – FlatBuffers são menores e mais rápidos de serem processados que conteúdo JSON. Obviamente nem tudo são flores: é necessário manter um arquivo de esquema e garantir que tanto o gerador quanto o consumidor de conteúdo sigam este esquema. Além disso, não é trivial abrir um FlatBuffer e identificar ou modificar seu conteúdo como fazemos com um arquivo JSON – fazer mocks utilizando FlatBuffers é mais complicado, por exemplo.

Apesar disso, acredito que os ganhos são maiores que as perdas. Considerando o uso de dispositivos móveis, ao transferir um FlatBuffer se consome menos banda do usuário, o que também implica em menor consumo de bateria. Ao carregar o FlatBuffer se consome menos memória e menos tempo de processamento, fazendo com que a aplicação fique mais fluida, sem travamentos ou diálogos que indicam carregamento de dados – e novamente, levando a menor consumo de bateria.

Espero que esta série de posts tenha convencido você a utilizar FlatBuffers em suas aplicações! Continue acompanhando o talkitbr!

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s