Desenvolvendo para Android – Como Implementar Content Providers

Standard

Hello Team, Ja vai algum tempo desde o ultimo  pois  o tempo ficou meio curto para escrever  principalmente depois de ter começado o  nanodegree do Udacity que tem sido bastante animado, tenho aprendido varias novas técnicas no android e o melhor de tudo é poder fazer novos amigos dentro dos grupos e forums de discussões.

Para quem queira começar o desenvolvimento de apps para android ou levar os conhecimentos que ja tem ao próximo nível, pode dar uma olhada nos seguintes cursos Android Fundamentals e Android Nanodegree.

Voltando para a jornada que faziamos, no ultimo post estivemos a falar sobre como persistir os dados para a utilização offline logo após de descarregar da cloud.

Até então demos um passo realmente importante para garantir uma boa experiência de utilizadores pois em países como Moçambique( Meu amado pais) e outros países africanos onde a conectividade a Internet não é estável e disponível para todos, o utilizador poderá ver as informações mais importantes mesmo quando a ligação a internet não esta disponível. Sendo especifico, o ultimo post focou-se nos seguintes pontos:

  • Como criar um contracto que contem a informação sobre as tabelas da nossa base de dados.
  • como usar o SQLiteOpenHelper para criar a base de dados com as tabelas definidas no contracto.
  • Como usar o android testing framework para poder testar se os dados estão a ser inseridos e lidos devidamente.

Com o os pontos mencionados acima, podemos criar uma boa experiência offline, fazendo a inserção e leitura dos dados ao SQLite de forma directa utilizando os métodos expostos pela class SQLiteDatabase.

Esta forma é bem rápida e fácil de implementar mas desvantagiosa pois em casos em que queremos partilhar as informações na nossa base de dados com outras aplicações (Exemplo: a app de contactos e o calendário partilham os seus dados para outras aplicações) a outra aplicação não só teria de saber que tipo de dados precisa mas como a leitura e escrita desses dados foi feita do nosso lado.

Felizmente, no android foi criado um componente denominado Content Provider que permite que apps possam partilhar informações umas  com as outras, encapsulando todo o código assim como o tipo de armazenamento utilizado para a escrita e leitura de dados fazendo com que os desenvolvedores da outra app só precisem saber qual a Uri(ja falamos sobre isso) para a informação que desejam.

Sendo assim se quiséssemos obter na nossa aplicação um filme guardado no dispositivo através de um Content Provider, seria desencadeado o seguinte processo:

  1. Especificamos a Uri, ou por outras palavras um caminho que identifica os dados no Content Provider. Um exemplo de uma Uri e a seguinte String  : content//com.app.mymooviapp/movie/2  que representa um filme com o id 2 dentro de uma tabela movie. Esta  Uri assim como as outras contem 2 partes importantes em que a parte ‘com.app.mymooviapp’  o content authority que representa o nome de todo provider e a parte ‘/movie/2′   que representa o path,o caminho para as tabelas e neste caso em concreto para um dado existente na tabela.
  2. A Uri especificada e(add acento) mais a operação que desejamos efectuar(insert,delete,update) são  passados  ao Content Resolver   que será responsável por dividir a Uri, pegar o content Authority  para procurar pelo Provider na lista conhecida pelo sistema e após encontrar o provider, a partir do path conseguir realizar a operação especificada sobre o(s) dados no path.

A questão que viria logo após o ultimo paragrafo seria como e que o sistema tem conhecimento do nosso Content provider e a content authority.

A resposta para essa pergunta é que assim como as Activities, os Content Providers devem ser registrados no androidmanifest e é especificado o nome da classe com a sua implementação e o content authority.

3. O content resolver nos da uma resposta de acordo com a operação que queriamos efectuar.(query  retorna Cursor, inser retorna int e mutio mais como especificado na documentação.)

Sabendo agora como funcionam os Content Providers, vamos passar para  a melhor parte que e(acento) a implementação de um content providers que será responsável por ler e escrever informações sobre os filme e para tal existem os seguintes passos que temos de seguir:

  1. Criar os contratos de dados e a base de dados.(Como no post anterior)
  2. Dentro do contracto denfir o BASE_CONTENT URI que ira representar o caminho para o “topo do provider”, e dentro de cada uma das classes internas ao contrato que representam uma tabela em outras palavras  um Content URI que representa o caminho ate a tabela.
basepath

Base Content URI. URI para o topo do content provider

Content Uri e Content type strings para a tabela Movie

Exemplo de Content Uri e Content type strings para a tabela Movie dentro do Contracto

3.Pensar e entender que tipo de leituras e escritas de dados iremos fazer para que possamos construir Uris apropriadas. Esta é a parte mais difícil do processo pois temos de conseguir pensar de antemão algumas coisas que não podem estar mais claras no principio. Um exemplo do que pensar nesta fase que veremos mais abaixo é por exemplo se vamos precisar de procurar filmes pelo titulo? pelo id? etc etc.

4. Apos pensar nas possíveis operações de leitura e escrita, devemos métodos auxiliares para gerar Uris dentro das classes correspondentes as tabelas no nosso contracto. Note que cada classe ou tabela terá diferentes métodos pois para tabelas diferentes podemos ter fazer a leitura de dados de forma diferente e com parâmetros diferentes como esta neste ficheiro de contracto disponível AQUI.

5.Com as Uris criadas, devemos criar uma classe e fazer com que ela extenda de Content Provider e registrar no android manifest( caso seja criada utilizando o wizzard será registrada automaticamente). Ao estender a classe Content Provider, esta obriga-nos a implementar alguns métodos importantes como (insert, delete, update, etc).

6.IMPORTANTE: Criar variáveis do tipo de dados inteiro que irão representar cada uma das Uri’s. (Exemplo: MOVIE_ID=100).

uri matcher variables

7. Criar um Uri matcher que será responsável por mapear os inteiros especificados no passo anterior a um determinado caminho. Ao fazer o mapeamento das Uri’s, é importante ter em conta que os  parâmetros do path ao invés de ter o nome escrito, devemos colocar um # (especifica que o parâmetro e um inteiro ou numero) ou um * (especifica que o parâmetro pode ser qualquer tipo de texto) para a parte do path que pode ser variavel. Na Uri content://com.app.mymooviapp/movie/2 o especificamos o id do filme mas em situacoes reais dentro da app esse id pode ser um numero qualquer. Sendo o id um numero variavel a Uri que apropriada para colocar no matcher deve ser content://com.app.mymooviapp/movie/*  onde no fim especificamos que vem um numero que nao sabemos qual .

Uri Matcher dentro da classe Content Provider

Uri Matcher dentro da classe Content Provider

8.Depois de fazer o match de todos inteiros as Uri’s, a magia ja esta quase pronta para acontecer e um ultimo passo antes de começar fazer aquilo que e o nosso verdadeiro objectivo de escrever e ler dados, e(acento) inicializar o content provider pelo método on create que se encontra dele mesmo. Este método e o local on o provider e inicializado durante o startup da nossa aplicação e todo processamento e feito na Main thread e como vimos no post, não podemos colocar operações pesadas dentro da main thread. O ideal aqui e fazer inicializações como criar uma instância do nosso SQLiteOpenHelper, SQLiteDatabase. Uma coisa extremamente importante neste método é que retorna um boolean que significa se o provider foi bem inicializado ou não. No caso do nosso provider, não fizemos nenhuma verificação e garantimos que o provider retorna true.

on Create dentro do Content Provider

on Create dentro do Content Provider

9. O ultimo passo da implementação do content provider, é a implementação dos métodos insert, query, update, delete que são os responsáveis por fazer a inserção, leitura, actualização e remoção dos dados respectivamente. Implementar estes métodos e relativamente fácil , mas e preciso tomar em conta o seguinte:

a. Todos estes métodos recebem uma Uri quando são invocados pelo content resolver e a primeira coisa que temos de fazer e utilizar o matcher quer criamos no passo 7 para encontrar o equivalente em inteiro a string do Uri.

b. Com o valor numérico que conseguimos ao mapear a Uri, devemos realizar um Switch case para que no mesmo método possamos tomar conta de varias Uris e realizar varias operações de forma diferente.

Exemplo de implementação do método Insert

Exemplo de implementação do método Insert

c. No fim das operações, antes de retornar o tipo de dados que cada método obriga, devemos notificar ao content resolver sobre a mudança na fonte de dados para que todos os cursores associados  e esta fonte possam actualiza-los de forma instantânea.

Notifica a mudança de conteúdo

Notifica a mudança de conteúdo

Os passos acima não são um guia definitivo, mas sim os aspectos que tomei e costumo tomar em conta no momento de implementar Content Providers. Por experiência própria, a melhor forma de aprender a implementar content providers, é implementando e lendo o código de outras implementações. Um exemplo de código super interessante de implementacao de content providers, é a aplicacao do google io 2015 iosched a qual aprendi varias coisas e encontrei classes auxiliares como Lists,Maps e SelectionBuilder(A classe ideal para remover a necessidade de pensar em detalhes de queries SQL) como poderam ver na classe final do nosso Movie Provider.

Uma outra dica no momento de implementar os content providers, e efectuar os testes de cada um dos métodos de forma individual e garantir que cada um deles, cada uma das Uri’s esta a funcionar pois ao testar no fim da implementação podemos ter erros muito difíceis de resolver principalmente nas primeiras vezes. A Classe que utilizei para testar os métodos do provider encontra-se aqui.

Espero que este post tenha aumentado o vosso arsenal como de armas ninjas como desenvolvedores para android e que seja mais um passo da emocionante e fantástica aventura que temos pela frente.

Para qualquer questão, como habitual podem postar um comentário abaixo ou agora um hangout request para qualquer dia no período das 21h as 22h (Maputo GMT +2) que ficarei feliz de vos ouvir e trocar opiniões..

Link do Projecto : MyMooviApp

Abraços

DM,

Advertisements

Android Support Library v22.1 – Como Comecar

Standard

No último post e o primeiro da  nova secção do blog, fiz a introdução a nova biblioteca do support v22.1 que veio melhorar a vida dos programadores permitindo implementar o material design e passar uma experiência única para todos  os dispositivos incluindo os que antecedem ao lolipop.

Para quem não teve a oportunidade de ler sobre as bibliotecas de suporte e  que novas ferramentas estão disponíveis pode fazer aqui.

Como o último post foi apenas sobre uma visão geral das novidades adicionadas,  neste post iremos olhar para o tópico de forma mais técnica e criar um novo projecto. Sendo assim, este post estará divido nas seguintes partes:

  • Como colocar as dependências para a nova biblioteca de suporte.
  • Como configurar o tema para implementar o Material design.
  • Implementar o Toolbar e Navigation Drawer.
  • Mudar cor do icon da linha seleccionada no Navigation drawer utilizando a classe DrawableCompat.

Para começar com a parte divertida do post vamos criar um novo projecto .No momento de escolher o minimumSDK, escolham a API 8 pois é do nosso interesse levar as funcionalidades novas para as versões mais antigas.

Depois de criar o projecto, temos de ir até a pasta app e clicar no ficheiro build.gradle para adicionar ou modificar as dependências de forma que possamos utilizar a nova versão da biblioteca de suporte.

Como nos criamos um novo projecto é possível ver dentro da secção dependencies { }  a linha compile ‘com.android.support:appcompat-v7:22.1.0’  como mostra a figura abaixo que indica que já temos esta dependência incluída por defeito. Para quem esta a modificar um projecto existente, basta substituir a linha similar caso exista ou copiar e colar caso não.

build.gradle

build.gradle

De seguida basta só fazer save no projecto e clicar em syncnow que aparece no canto superior direito do editor para que o gradle comece a fazer a resolução das dependências. SIMPLES 🙂

Com a nova biblioteca de suporte incluída no projecto, vamos continuar a construção do projecto passando para o passo seguinte que é a definição do tema da nossa aplicação seguindo as guidelines do material design.

Para definir temas na nossa aplicação, devemos criar um ficheiro themes.xml  que é onde estará o nosso código xml com a definição do tema.

Create Theme xml file

O ficheiro que acabamos de criar, irá conter os atributos do tema, que são suportados pelas versões que antecedem o lolipop. De forma a fazer com que o mesmos temas tenham o comportamento  incluindo as funcionalidades somente existentes no lolipop, devemos  criar uma pasta com o nome values-v21  dentro da pasta res e copiar para dentro da mesma o ficheiro themes.xml que criamos acima.

Create Values 21 folder

Criado o ficheiro, vamos colocar o conteúdo neles e definir o tema que utilizaremos na nossa aplicação e para tal  vamos copiar o código disponível nos seguintes gists: values->themes.xml e values-v210->themes.xml.

Na construção destes ficheiros, é preciso ter em conta que todas as tags <style>  tem os atributos name parent  que representam o nome que vai identificar o tema e o pai de quem herdar os atributos respectivamente.

De seguida temos de utilizar a  tag item de forma a definir os atributos do tema. Os atributos mais importantes a ter em conta são:

  • primaryColor: Define a cor principal que será  utilizada no toolbar  ou outra área que ocupe muito espaço.
  • primaryColorDark: Define a versão mais escura da primary color que será utilizada no status bar.
  • colorAccent: Define a cor de contraste que é utilizado para colorir acções que precisam da atenção do utilizador.

NB: A Paleta de cores assim como as regras que ditam que tons escolher para cada um dos atributos encontra-se aqui!

Com o tema definido, resta-nos só ir até ao ficheiro androidManifest e definir que a aplicação deve utilizar o tema criado como na figura baixo.

ChangeTheme

Ate então, se clicarmos no botão do Run para executar o projecto, a nossa aplicação ira abrir e só será possível ver uma tela branca com o status bar da cor que definida e para a grande surpresa, SEM ACTIONBAR.

A ActionBar não aparece  pois dentro do ficheiro themes.xml  nós definimos que iríamos herdar os atributos do tema AppCompat.NoActionBar que significa que o tema não terá um actionBar. Herdamos este tema de forma que no lugar do Actionbar possamos utilizar o novo componente introduzido no material design chamado Toolbar.

Para continuar com o post, vamos de seguida definir o Toolbar e colocar o navigation drawer  no nosso layout. Para poder ter o navigation Drawer, temos de ter como raiz o LayoutManager DrawerLayout disponível no pacote android.support.v4.widget.DrawerLayout e dentro dele colocamos a ListView, o Toolbar e o FrameLayout que será utilizado para trocar os fragments ao selecionar uma determinada opção no Drawer. O código do layout da main activity encontra-se AQUI.

Passando para o código java correspondente a MainActivity disponível aqui, temos de dar especial atenção ao seguintes pontos:

  • a nossa Activity  passou a extender a AppCompatActivity devido a depreciação da ActionBarActivity na versão nova da biblioteca de suporte.
  • no método inicializarToolbar, pegamos o Toolbar pelo seu id, e podemos definir o título, subtítulo etc como faríamos em uma ActionBar normal.

Pouco antes do lançamento desta biblioteca, era comum definir o ActionBar apartir do Toolbar fazendo  setSupportActionBar(Toolbar toolbar)  e passávamos a ter uma actionbar bastando fazer getSupportActionBar().

Mas Porque no Material design o conceito ActionBar foi deixado para trás, neste post nos utilizamos o Toolbar para definir o titulo, definir o icon do navigation drawer fazendo setNavigationIcon passando o Drawable do icon e por fim definir um evento para ficar a espera de clicks no icon utilizando setNavigationOnClickListener.

  • no método inicializarDrawer
    • começamos por pegar o DrawerLayout e a ListView pelos id’s.
    • Inicializar o ActionBarDrawerToggle e um listener para que possamos saber quando o drawer esta aberto ou fechado pelos métodos que temos implementar onDrawerOpened ou onDrawerClosed respectivamente.
    • definir o listener criado no passo anterior ao DrawerLayout
    • Criar um Adapter para a Lista do NavigationDrawer.( A criação do adapter e feita como neste Post. A grande diferença neste adapter é que temos na mesma lista dois tipos de linhas diferentes em que o primeiro tipo representa o Header com um background e o espaço para uma foto de perfil e o segundo tipo é apenas uma linha com um icon e um texto.)
    • Definir o adapter na lista.
    • Para terminar este método, registamos um listener que irá ficar a espera dos clicks nos itens da  lista.

A parte interessante deste post, é a que se segue em que ao clicar em um item do navigation drawer, mudamos a cor do texto da linha assim como a cor do icon mudam utilizando a nova classe DrawableCompat.

Para atingir tal objectivo, temos de:

  • criar duas variáveis globais( mPosicaoSelecionada mUltimaPosicaoDoDrawer) para guardar a posição do item seleccionado no drawer e a posição do item seleccionado anteriormente. Estas duas variáveis começam com o mesmo valor mas ficam diferentes depois que um item é clicado pela primeira vez e é invocado o método onItemClick  do listener da lista.
  • Depois de definir as variáveis, fechamos o drawer utilizando mDrawerLayout.closeDrawer(mListaDrawer).
  • Implementar o método para  mudar as cores da linha seleccionada( pintarItems ) dentro do callback onDrawerClosed pois é o único momento em que não temos o drawer aberto e podemos fazer as mudanças sem que utilizador note antes da próxima vez que ele abrir o drawer. Na implementação do método pintarItems :
    •  pegamos a view da lista correspondente a posição passada no método.
    • pegamos a view que contem o icon e o texto o texto das linhas
    • pegamos o drawable definido como background na view do icon e fazemos o wrap pelo DrawableCompat.
    • verificamos com o boolean passado se estamos a querer pintar ou colocar a linha na cor normal e definimos a devida cor.
    • Mudamos a cor do texto do Textview e fazemos o tint do drawable fazendo DrawableCompat.setTint(drawable,color).

Feitos os últimos passos, completamos a nossa aplicação e ao executa-la, temos o navigation drawer a funcionar devidamente e a mudar a cor do icon da opção seleccionada utilizando o DrawableCompat e eliminando o sofrimento de ter Drawables de cores diferentes para gerir os diversos estados que podemos querer representar.

PostSupportPic0 PostSupport002

Desta forma chegamos ao fim do post e mais uma vez espero que acima de tudo tenham se divertido e dado mais um passo para que se possam tornar desenvolvedores Ninjas.

Até a próxima 🙂

DM!

Links:

-Github: https://github.com/realdm/PostSupportLibrary

A Nova Android Support Library V 22.1 – Visão Geral

Standard

Hello a todos os Devs e espero que estejam todos muito bem de saúde e com disposição para mais um post ! Depois de algumas semanas extremamente agitadas, finalmente tive a oportunidade de voltar a escrever!

A minha volta veio com algumas reestruturações no blog em que decidi organizar melhor os posts da série para os iniciantes no desenvolvimento de apps  para android, criando novas secções em que pudesse escrever sobre tópicos mais avançados ou novidades sobre o mundo do android. Para quem esta a ler o blog pela primeira vez e gostaria de iniciar o desenvolvimento de apps para android pode começar a serie AQUI ou escolher a secção “Android – Iniciantes”.

Esta nova secção com o nome “Android Geral” terá como objectivo, escrever sobre alguns temas, tutoriais mais avançados e específicos como a utilização de APIS( Google Maps, Places, Youtube, Google Cloud Messaging), animações, etc.  A decisão de criar essa nova secção foi baseada no desejo da vontade de me desafiar e partilhar conhecimentos mais avançados assim como organizar melhor os posts para que o pessoal que esta a começar possa ter uma melhor orientação e saber que caminho seguir no blog.

E para abrir este novo espaço, neste post irei falar sobre a nova versão da  Android Support Library V22.1 que veio para animar a festa e deixar os desenvolvedores com menos dor de cabeça.

Para quem não sabe, a Android Support Library  é uma biblioteca desenvolvida pela Google que como o nome sugere oferece suporte a funcionalidades de API’s avançadas as API’s mais antigas, isto é, permite que os desenvolvedores possam desenvolver uma  certa funcionalidade disponível em uma das versões (Ex: Lolipop) e fazer com que funcione da mesma maneira em versões mais antigas (Ex: ICS). A Support Library  vem sendo desenvolvida já a muito tempo e um dos momentos mais marcantes foi  a possibilidade de utilizar o ActionBar que só era disponível para as API 11+ em aplicações que utilizavam as API’s inferiores.

Com o surgimento do Material design na versão 5 do android (Lolipop), novos padrões, componentes e funcionalidades foram adicionadas e desde o lançamento no ano passado, vários desenvolvedores tem vasculhado o código fonte para poder recriar  a experiencia do Lolipop nas versões anteriores. Tendo esta situação em mente, na altura a equipe do Google decidiu fazer pequenas actualizações na biblioteca de suporte já existente de forma enquanto preparavam o lançamento da mais recente Android Support Library V22.1

O lançamento desta biblioteca veio com varias funcionalidade novas, muito bem descritas no blog oficial AQUI mas para este post, apenas irei focar-me nos aspectos que mais me chamaram atenção e que considero  muito interessantes.

A primeira novidade  e a introdução do DrawableCompat, uma classe que permite fazer o Tint de drawables(Falei chinês). Com o Tint  de drawables quero dizer a possibilidade de poder mudar por exemplo a cor de um icon durante o tempo de execução sem ter de disponibilizar o mesmo icon com cores diferentes. Para quem tiver a app “Play Newsstand” poderá notar a  mudança de cor do icon de um item quando seleccionado no navigation drawer. Para poder utilizar a classe e fazer o Tint basta encapsular o Drawable no método DrawableCompat.wrap(Drawable) e de seguida invocar os métodos seleccionados como o setTint(), setTintMode etc.

A segunda novidade e a classe ColorUtils  que oferece ferramentas para melhor trabalhar com cores permitindo calcular a relação do contraste entre as cores, a opacidade de forma a manter um determinado contraste. (Estas ferramentas são perfeitas para manter um texto legível quando por cima de uma imagem).

A terceira novidade e a introdução de Interpolators, que permitem controlar  a variação de uma determinada animação. O Lolipop já veio com vários interpolators que permitiram criação de animações bem suaves e de diferentes tipos. Ainda nas animações, foi também adicionado o PathInterpolatorCompat  que permite a criação de curvas de beizel quadráticas e cúbicas(Para mais informações sobre Path e curvas de beizel veja AQUI)

Indo mais para o nível de Activities  e Widgets, existem 4 coisas que foram algumas modificadas e outras adicionadas:

  • Houve uma depreciação da ActionbarActivity para AppCompatActivity. Esta mudança não foi apenas no nome mas  na utilização da classe AppCompatDelegate que para vos ser sincero ainda estou a tentar entender o que  é e como funciona. Entretanto muitas das aplicações não precisam chegar ao detalhe de mexer com AppCompatDelegate pelo que no uso diário, convem extender a Activity da classe AppCompatActivity.
  • Adição do Material Design Dialogs permitiu a criação de dialogs(“pop ups) com o estilo do Material design utilizando a class AppCompatDialog e actualizando a antiga classe AlertDialog  para que tenha as mesmas capacidades.
  • Voltando ao primeiro aspecto sobre o Tinting falado acima, e possível (Finalmente =) )fazer o mesmo com widgets(Botões, TextView, CheckBoxes). Para tal, foram criados novos widgets com esta capacidade para substituir os antigos com os seguintes novos nomes:
    • AppCompatAutoCompleteTextView
    • AppCompatButton
    • AppCompatCheckBox
    • AppCompatCheckedTextView
    • AppCompatEditText
    • (Mais no blog oficial)
  • O quarto e o último aspecto é a capacidade que já tinha sido lançada no Lolipop de poder definir um tema para cada View, permitindo por exemplo colocar o Toolbar com um tema e cor diferente do tema da activity ou do resto dos componentes. Na versão antiga para definir o tema na Toolbar  era preciso definir o namespace app e na view  fazer app:theme=”<tema>” .O Atributo to theme foi adicionado ao android namespace permitindo que qualquer view na API 11+ possa definir seu próprio tema fazendo android:theme=”<tema>”.

Existem muito mais ferramentas como a Pallete , RecyclerView, RenderScript que foram adicionadas e que permitem a criação de novas  experiencias consistentes para todas as versões do android existentes.

Como desenvolvedor, fico grato a equipe da Google por lançar o update e espero que todos vocês façam uso destas novas ferramentas para desenvolver altas apps!

Caso tenha algum comentário ou questão, deixe ficar no comentário que poderemos continuar a conversa lá.

Muito Obrigado,

DM

Desenvolvendo para Android – Como persistir dados offline com SQLite

Standard

Hello Desenvolvedores, espero que estejam todos muito bem e bem dispostos para continuarmos com os posts da nossa serie. Só para lembrar e actualizar os que não tenham lido, no post anterior vimos:

  • como conectar a uma API utilizando as classes HttpUrlClient,
  • O que é a main thread e porque não devemos realizar operações que podem ser longas( realizar um pedido a uma api, descarregar ou descodificar uma imagem),
  • Como utilizar a classe AsyncTask para realizar operações fora da Main thread
  • e finalmente como descodificar a resposta do JSON disponibilizada por um pedido a API do openweather.org utilizando as classes JSONObject .

Só com o post anterior é possível criar aplicações para mostrar o feed de um jornal, tweets de um certo hashtag ou dados de temperatura como no nosso exemplo e da aplicação sunshine no curso do Udacity e disponibilizar no playstore. Só que apesar de funcionar, implementar uma solução desse jeito e publicar não seria uma boa experiência para o utilizador pois toda vez que ele abrisse a aplicação ou reiniciasse uma activity por algum motivo  teria de refazer os pedidos a API o que resultaria em um gasto constante de dados e de bateria por estar a utilizar o rádio do dispositivo de forma irresponsável.

Para resolver esses pequenos inconvenientes, o android oferece várias opções que permitem persistir os dados no dispositivo para que estejam disponíveis mesmo quando os dispositivo esta desligado da rede. As opções existentes são:

  • SharedPreferences : Mecanismo que permite guardar como forma de chave- valor informações dos tipos de dados primitivos. Muito prático para guardar algumas configurações como um boolean para verificar se o utilizador já fez o login antes mas pouco eficaz para guardar dados das estruturas complexas que normalmente temos nas aplicações. Este mecanismo é seguro pois só é possível ter acesso aos dados dentro da nossa aplicação.
  • Internal Storage (Memoria interna do dispositivo): este mecanismo permite guardar ficheiros directamente na memória do dispositivo. E para esclarecer qualquer questão, a escrita e leitura de ficheiros é exactamente como e feita tradicionalmente no java. Neste mecanismo só é possível ter acesso aos ficheiros pela aplicação e esta é toda apagada no momento que a aplicação é desinstalada.
  • External Storage(Memoria externa) : Este mecanismo permite guardar ficheiros directamente em uma memória auxiliar como microSD e tem a grande desvantagem de não oferecer segurança pois os ficheiros todos podem ser lidos e modificados pelo utilizador caso esteja a utilizar a memória no modo “mass storage”.
  • SQLite Database : O android oferece para base de dados em SQLite que podemos aceder pelo nome da base de dados apenas dentro da aplicação em que ela foi criada. Este mecanismo possui a vantagem de ser seguro e pratico para armazenar estruturas complexas.

A minha opinião é  de que todas as opções citadas acima são interessantes dependendo do caso em que precisaríamos utilizar mas para este post iremos utilizar a ultima opção que é  o SQLite Database.

Sendo assim, neste post iremos ver os seguintes pontos:

  • Criar uma classe que vai definir o contracto ou esquema da nossa base de dados.
  • Utilizar a classe SQLHelper para criar a base de dados
  • Utilizar o Framework de testes do android studio para realizar os testes em que iremos inserir, actualizar e remover os dados nas tabelas da nossa base de dados.

Começando pelo primeiro ponto, vamos pegar o projecto do post anterior, criar um pacote com o nome data como mostra a figura abaixo. De seguida vamos criar um classe chamada WeatherContract como esta no gist AQUI.

A classe que acabamos de criar irá conter classes internas que irão representar cada tabela da nossa base de dados, possuindo o nome das colunas e outros detalhes que iremos utilizar ao estudar content providers em posts mais a frente.

Criado o nosso contracto, vamos agora criar uma classe WeatherSQLHelper que vai extender a classe SQLiteOpenHelper. O SQLiteHelper, é uma classe que nos ajuda na criação, e gestão de versões da base de dados.

Para utilizar esta classe e criar uma base de dados, devemos criar um construtor que tenha a chamada para o método super, e reescrever o método onCreate(SQLiteDatabase db) que é o método onde todo processo de criação da base de dados e das respectivas tabelas é efectuado . Dentro desta classe definimos ainda parâmetros como o nome da  base de dados, a versão.

Ate então, o que nos resta, é  criar as queries para criação de tabelas usando o auxilio das colunas definidas estaticamente na classe do contracto acima.

Após criadas as strings para a criação das colunas, vamos , dentro do metodo onCreate, criar as tabelas utilizando o método execSQL(String string) da classe SQLiteDatabase que é  passada como construtor para o método com mostra o gist completo do helper AQUI.

Finalmente temos o nosso contracto criado, a base de dados e as tabelas.

Quando comecei a programar para android e mexi com o SQLite pela primeira vez, na hora de testar , tive de perder muito tempo para criar uma UI que me permitisse testar as operações de inserção, leitura e actualização para no fim ficar devastado ao descobrir que tinha um erro e não tinha nada haver com a UI que tinha perdido tanto tempo a criar.

Felizmente, as nossas ferramentas de desenvolveram tanto que hoje em dia o android studio possui um Framework de testes que nos permite testar só esta parte da base de dados sem que tenhamos de fazer o mesmo trabalho que tive aquela altura, permitindo testar a aplicação tomando cada parte da aplicação independente do resto da implementação.

Para começar, devemos dentro da nossa aplicação, do lado esquerdo onde tem a estrutura do projecto mudar a virtualização da estrutura do projecto para “Project” pois este pode estar em mais duas formas “Android” por default our “package”. Para tal vejam como  o fazer nas figuras abaixo.

Visualização da estrutura default- Android

Visualização da estrutura default- Android

ProjectView

A segunda figura mostra que dentro da pasta app->src, temos uma pasta chamada androidTest. Esta pasta é automaticamente criada pelo android studio quando se cria um novo projecto, e esta contem os ficheiro de testes que eventualmente podemos querer  utilizar na nossa aplicação, neste caso para testar a nossa base de dados. Vamos dentro do pacote principal dentro da pasta criar uma classe TesteDb e fazer com que a mesma extenda AndroidTestCase.

Feito isto para dar continuidade ao processo, antes de começar a escrever os métodos do teste, devemos configurar o Android Studio para que execute os testes como uma variante separada da nossa aplicação. Para isso basta:

  1. Clicar em Edit Configurations na lista que aparece antes da setinha verde do Run do IDE.

EditConfigurations

2. Adicionar uma nova configuração, clicando o botão verde com o sinal “+” mais a esquerda da janela aberta e escolher android tests.

AndroidTests

3. Copiar as configurações como estão na figura abaixo. Note  que o mais importante e  configurar o nome (Name) , escolher o “module” que normalmente costuma ser o “app” e definir que deve sempre mostrar a opção de escolher o dispositivo em que deseja executar os testes.

Configurations

Concluídas as nossas configurações, vamos voltar para o ficheiro de testes e escrever os métodos como estão no gist AQUI.

Ao clicar na setinha verde para executar a configuracao de testes, se estiverem a utilizar um dispositivo real ira mostrar a tela normal para executar no dispositivo e  os testes serao iniciados mostrando o resultado como na figura abaixo.

Tests Passed

Com os testes efectuados e todos limpinhos, chegamos ao fim de mais um post e desta vez desafio-vos a implementar  os testes que faltam como a inserção, leitura dos dados da previsão.

Mais uma vez obrigado pela atenção ao ler este post e espero poder ter contribuído no teu caminho de Ninja android dev.

Abraços!

DM

Desenvolvendo para Android – Como descarregar dados da cloud utilizando uma AsyncTask

Standard

Depois do ultimo post em que vimos mecanismos para carregar os dados  de uma fonte como um array e fazer com que sejam disponibilizados em uma ListView, vamos continuar a Série e aprender como fazer coisas mais interessantes e nos tornarmos em Desenvolvedores Android Ninjas. Várias vezes queremos fazer aplicações para mostrar horários dos filmes de um cinema, mostrar os últimos tweets de uma certa tag, mostrar os vídeos de um canal do youtube ou mostar os posts de uma determinada conta do Tumblr mas não sabemos necessariamente por onde começar e fazer com que a nossa idea ganhe vida.

Para que possamos superar estes inconvenientes, neste post irão aprender como:

  • O que é uma API?
  • Exemplos de API’s Interessantes.
  • Conectar a uma API utilizando o protocolo HTTP.
  • Realizar a operação de conexão a API dentro de uma AsyncTask
  • O que é o JSON.
  • Processar a resposta do API disponibilizado em formato de um JSON.
  • Mostrar os dados em uma ListView.

O que é uma API?

Uma  “Application Programing Interface”  ou normalmente conhecida pelo seu acrónimo API, é um conjunto de padrões ou instruções de programação para o acesso a uma aplicação   ou as suas funcionalidades sem que haja a necessidade saber como a aplicação ou funcionalidade foi desenvolvida. Várias empresas como Google, Facebook, Twitter etc, desenvolvem API’s para que os programadores possam criar e implementar aplicações terceiras que usufruam dos serviços oferecidas por eles. Uma das API’s mais comuns de ver tanto em websites como em apps, é a API dos Maps disponibilizada pela Google que permite que o Web Developer possa colocar um mapa no seu website utilizando apenas um código disponibilizado ou que mobile App Developers possam utilizar serviços de localização em suas aplicações. Abaixo estão listadas algumas API’s muito utilizadas no mundo:

Para dar continuidade ao post,  iremos de seguida escrever o código para conectar ao servidor do OpenWeather API, buscar os dados de temperatura para uma determinada cidade e de seguida processar a resposta e disponibilizar na lista do projecto criado no post anterior.

Para começar vamos abrir a classe FragmentLista e adicionar o método disponível no gist aqui. O método adicionado será responsável por fazer uma conexão pelo protocolo http a url que ele recebe como parâmetro e ira devolver uma string como resposta que nos esperamos que seja a resposta no formato JSON do pedido que tenhamos feito a url. Explicando um bocadinho o que acontece neste método,o processo e o seguinte :

  • Primeiro criamos uma url apartir da string que o método recebe como parâmetro utilizando a classe URL.
  • De seguida Criamos e inicializamos uma conexão a url criada no passo anterior. Para inicializar a conexão podemos utilizar a classe HTTPUrlConnection ou outras bibliotecas como OKHTTP(Oferecem melhor performance).
  • Por fim fazemos a leitura dos bytes do fluxo de entrada (InputStream) e vamos construindo uma String utilizando a classe BufferedReader e fazer com o método a retorne.

Ate então, se por algum motivo decidíssemos invocar o método neste momento, poderíamos nos deparar com o erro  android.os.NetworkOnMainThreadException  que é causado por estarmos a fazer uma operação de connectar a rede que não sabemos em que momento poderá terminar dentro da thread princiapl Main.

Este erro acontece porque de acordo com as especificações disponíveis aqui, a Main thread é responsável por despachar eventos para um determinado widget da interface gráfica e interagir com o Android UI toolkit (componentes do pacote android widget e  android.view).

Pelas razões citadas a pouco, realizar tarefas que não sabemos em que momento terminariam dentro da main thread vai fazer com que a nossa aplicação não consiga reagir aos eventos activados pelo utilizador e posteriormente causar com que a aplicação pare de Executar.

Dentro de uma AsyncTask somos obrigados a implementar um método de nome doInBackground mas maioria das vezes podemos querer implementar pelo menos os 3 métodos abaixo:

  • onPreExecute(): O método onPreExecute é executado antes de iniciar a nova thread no background para realizar o trabalho que nos pretendemos . Este método é executado na UI Thread.
  • doInBackground(Params… param): o método do In background é onde realizamos todas as nossas operacoes que não sabemos quanto tempo podem levar (descarregar uma imagem, connectar a uma API). Este método recebe um parâmetro  do mesmo tipo que passamos ao extender a classe e retorna também o tipo de dados definido ao extender a classe. Este método e executado fora da UI Thread.

onPostExecute(Param param): O método on post execute é invocado de volta na UI Thread e recebe como parâmetros os dados retornados pelo método doInBackground. É neste método que podemos começar a definir os dados nos componentes após o fim do método doInBackground.

No nosso caso, ao executar o pedido o servidor responde-nos com uma String em formato JSON. Mas afinal de contas o que é o JSON?

JSON significa JavaScript Object Notation, e  é um formato muito utilizado para troca de dados. O JSON tem várias vantagens como permitir  a facil leitura e escrita pelos seres humanos assim como pelos computadores.

Basicamente o JSON representa os dados em forma de chave-valor e podem ser representados tipos de dados primitivos, objectos e arrays. Para mais informações sobre o JSON a W3Schools tem um tutorial muito bom AQUI

Para descodificar a resposta do nosso servidor que está no formato JSON, vamos utilizar duas classes bastantes úteis para o efeito que são JSONObject e JSONArray. A implementação completa do AsyncTask como uma classe interna do Fragment que temos a lista encontra-se AQUI.

Com a AsyncTask criada, só nos resta modificar o código dentro do onCreate() do fragment em que fazemos o set do adapter com o array que tinhamos pre-definido, para utilizar a asynctask como esta aqui.

Conclusão

Com este post foi possível aprender o básico de como fazer conexao a uma url utilizando o protocolo HTTP e como fazer de forma correcta para  que esta tarefa seja executada em uma thread que nao afecta a responsividade da nossa aplicação. Gostaria de terminar o post dizendo que a idea do fundo deste post em particular era deixar a conhecer a classe AsyncTask como forma de realizar operacoes(descodificar bitmaps, descarregar dados da rede etc.) em uma thread separada . Para o nosso exemplo em que estávamos a fazer uma conexão a uma API, existem bibliotecas como OkHTTP e Volley que permitem fazer o mesmo de forma muito mais eficiente.

Como sempre, espero pelos feedbacks, questões etc.

Ate mais =)

DM!

Desenvolvendo para Android – Lista e Adapters

Standard

Depois dos últimos posts da serie em que estivemos a ver o básico sobre o desenvolvimento do android, chegou a hora de começar a entrar em tópicos um pouco mais complicados que necessitam a junção de todos os conhecimentos adquiridos ate a data. Neste post iremos aprender

  • Como criar uma lista.
  • Como popular os dados da lista utilizando um Adapter.
  • Como registar eventos de “click” a cada item da lista e iniciar uma Activity com os dados do item correspondente.

Resultado esperado no fim do post:

device-2015-02-25-124754 device-2015-02-25-124823

Uma ListView é um widget disponível no android utilizado para mostrar dados em forma de uma lista. Cada item da lista é uma view que pode tomar qualquer apresentação que quisermos dependendo do ficheiro de layout definido como veremos posteriormente.  Para começar, vamos criar um novo projecto, criar um Fragment, abrir o ficheiro de layout do fragment e copiar o código disponível neste gist. De seguida vamos abrir  código java do nosso  fragment e dentro do onCreateView() vamos criar uma instância da classe ListView e fazer a ligação ao widget utilizando o id definido no xml como esta disponível no gist aqui.

Nota: Como vimos no post anterior, o método onCreateView recebe 3 parametros importantes nomeadamente um LayoutInflater, ViewGroup, Bundle e como foi explicado o layout inflater e utilizado para desenhar uma View(neste caso o nosso layout do fragment disponível na pasta res->layouts). Ao criar uma instancia da classe View e utilizar o inflater fazendo View  view =inflater.inflate(int layout,ViewGroup parent,boolean attachToParent), estamos a desenhar o layout que depois e retornado pelo método getView. Para pegar encontrar um widget com um determinado id no XML, diferentemente de uma activity que faríamos TextView textView = (TextView) findViewById(R.id.text), aqui nos temos que explicitamente dizer em que view nos desejamos fazer o findViewById(int id) e para o nosso exemplo faríamos ListView list = (ListView) view.findViewById(R.id.lista). E a razão para este procedimento, e que as classes Activity, ActionBarActivity ou FragmentActivity de que extendemos possuem uma instancia da classe View em que na implementacao do método setContentView que temos acesso , o processo de desenhar o layout e feito assim como explicado acima.

Desenhada o layout do Fragment, criada a instância da lista e devidamente acoplada pelo id ao widget no ficheiro xml, vamos criar um componente bastante importante  na criação de listas. Esse componente tem o nome de Adapter e a sua funcao é de pegar os dados de uma fonte(Base de dados, array), desenhar cada item da lista e preencher os campos necessários com os dados recebidos. Para criar uma adapter vamos primeiro criar uma classe normal  atribuir um nome sugestivo e fazer com que ela estenda da classe BaseAdapter. De seguida o android studio mostra um erro e para resolver basta fazer o ctrl+i para implementar todos os métodos a ré-escrever:

  • getCount():int – O método getCount requer que se devolva um inteiro e este representa o numero de dados que queremos apresentar no listview. Se por exemplo fizermos o return de 3, o nosso listView so apresentara 3 elementos. E sempre aconselhável fazer o return do tamanho do array ou da Lista que temos.
  • getItem(int):Object –  O método getItem faz o return do item na posição passada. No nosso caso faz o return de uma string do array que encontra-se na posição passada como parâmetro.
  • getView(View,ViewGroup,int): view – O método getView é mais importante do adapter pois ele é que é responsável  por desenhar cada item da lista e reciclar um item que já não esta visível  na tela para que seja utilizado para popular os dados por vir no item da lista mais abaixo.Ele recebe uma view que no inicio da criação da lista ele sempre vem null ate a criação de todas as views visíveis na tela. No momento em que o utilizador faz o scroll, ele pega as views que não estão mais visíveis para o utilizador e faz a reciclagem para que sejam re-utilizadas para popular as views que estão por vir com novos dados da lista. Neste método devemos seguir os seguintes passos  para desenhar a view e popular com os dados :
  • Pegar o Context da aplicação utilizando o ViewGroup passado ou ate uma variável global passada ao construtor do Adapter.
  • Criar um LayoutInflater a partir do Context que utilizaremos para desenhar a view.
  • Utilizar o inflater para desenhar a view a partir do ficheiro de layout que representa cada item da lista.
  • Fazer os findViewById(int) dos componentes que temos dentro do layout da linha da lista.
  • Popular estes componentes com dados.

Fazer o return da view criada dentro do método.

A implementação comum do getView encontra-se aqui. O mau desta  implementação e que sempre que entramos  neste método e a view for null, teremos de fazer sempre uma nova instância e chamar o findViewById o que não é muito bom em termos de eficiência. Para resolver este ficheiro basta criar um ViewHolder que não é nada mais que um classe que contem a instância de todos os nossos componentes, onde fazemos o findViewById uma única vez e no nosso getView simplesmente pegamos uma instância deste objecto e os componentes la dentro já estão  devidamente mapeados aos widgets no xml e temos apenas de popular com os dados. A implementação final do adapter em que  utilizamos o ViewHolder encontra-se aqui.

Com o Adapter pronto, o que temos de fazer de seguida é voltar para o nosso fragment, criar uma instância do nosso adapter, passar os dados que queremos apresentar na lista(neste caso um array de Strings) e de seguida fazer definir o adapter fazendo listView.setAdapter(Adapter) como esta no seguinte gist.

Com todo o código que temos ate agora, ao executar a aplicação conseguiremos ver uma lista com os dados que definimos.

Para terminar o post, vamos fazer com que ao clicar em algum item da lista, seja chamada outra Activity e que esta nos deve mostrar os dados do item da lista que clicamos. Para isso primeiro temos de criar uma Activity( botão direito do Mouse -> new -> Activity -> Blank Activity) e de seguida modificar o id do textView do ficheiro de layout da Activity para que tenha um identificador para que possamos definir o texto que vem da nossa lista(Gist). De seguida temos de voltar ao fragment que tem a nossa lista e definir o onItemClickListener listener que ficara a escuta de eventos de click a cada item da nossa lista. Na implementação deste método iremos pegar o valor do item naquela posição da lista utilizando o adapter passado ao método, criar um Intent para iniciar uma nova activity como vimos aqui() e passamos uma string como extra atribuindo uma chave única terminando por iniciar a nova activity fazendo startActivity(Intent) como esta no gist final do Fragment.  Para completar voltamos a Segunda Activity e após ter uma instância do TextView e mapear ao widget no xml pelo seu id, devemos pegar o Intent que invocou a nossa activity, pegar a String passada como argumento utilizando uma chave e fazer o setText no textView(Gist). Para terminar, só nos falta executar a aplicação e testar o que estivemos a fazer ao longo do post.

Desafio: Modifiquem a vossa lista para que passe a mostrar um icon e o nome do lado.

Dica: irão precisar de um array de icons do mesmo tamanho que o de nomes e modificar o layout responsável pelo desenho de cada item da lista assim como o método getView.

Links:

Projecto no github

ListaeAdapter.apk – ficheiro de instalacao da aplicacao

Como sempre, muito obrigado pelo tempo de leitura e ficarei a espera de comentários, duvidas ou sugestões de melhoria.

Abraços

DM

Desenvolvendo para android- Fragments

Standard

Depois de entender sobre a base de uma aplicação em android no ultimo post sobre ciclo de vida de uma Activity disponível  AQUI, chegou a hora de entender  o funcionamento de um componente tão importante como uma Activity. Um dos maiores desafios que os desenvolvedores encontram  no desenvolvimento de apps para android,  e a existência de vários dispositivos com  diversas formas e tamanhos.  Para criar uma aplicação que possa adaptar-se aos diversos dispositivos no mercado, é preciso entender componentes como Fragments e como estes podem ajudar-nos nesta tarefa.  Este post iremos aprender sobre :

  • O que são Fragments.
  • Como Funcionam os Fragments
  • Como utilizar os Fragments nas aplicações.

Para começar o post definindo e entendendo o que é um Fragment em apenas uma frase, eu diria que “Fragments são sub-Activities” e a  razão pela qual o descrevi em uma frase tão curta é que os fragments tem um ciclo de vida como uma Activity, tem interface gráfica(podem não ter) e estes só podem existir dentro de uma Activity. Indo um pouco a historia do android, os fragments apareceram pela primeira vez na API 11(Versao 3.0) com o surgimento dos primeiros tablets.

Estes novos dispositivos para o android originaram a necessidade de utilizar de forma eficiente o espaço que  apresentavam e proporcionar uma experiencia apropriada ao utilizador. A solução para este problema foi utilizar os Fragments como partes modulares da interface gráfica que podem ser combinadas ou separadas consoante o espaço do dispositivo. Para entender melhor esta ultima parte vamos tomar em considerarão o Gmail admitindo que esta é uma aplicação muito familiar para todos e considerar os cenários onde o utilizador abre a app utilizando um smartphone  ou um tablet.

Comecemos com o caso em que o utilizador abre a aplicação utilizando um smartphone e a primeira coisa que ele vê e uma Activity com a lista de e-mails recebidos na caixa de entrada e ao clicar em um dos e-mails, outra activity é aberta e esta  apresenta o conteúdo do e-mail como mostram as figuras abaixo.

Tela com a lista dos emails no Gmail

Tela com a lista dos emails no Gmail

Screenshot_2015-02-13-23-05-56

No segundo caso, o utilizador esta a utilizar um tablet e quando ele abre a aplicação, esta apresenta uma activity divida em 2 áreas onde mais a esquerda esta a lista dos e-mails da caixa de entrada e ao clicar em um dos e-mails, o conteúdo e apresentado na área maior a direita como mostra a figura abaixo.

unnamed

fragments

Passando para a parte interessante que e a criação de interfaces dinâmicas utilizando Fragments, vamos criar o nosso primeiro Fragment e para tal basta criar uma classe e estende-la da classe Fragment.(E sempre aconselhável utilizar a classe da biblioteca de suporte.)

Como disse antes, assim como o as Activities os Fragments tem um ciclo de vida e métodos de callback que representam cada estagio como e explicado aqui(Fragment LifeCycle Link). Para  este primeiro exemplo, os 2 métodos de callback importantes a saber sao são:

  • onCreate: Assim como uma Activity, o Fragment possui este método que e invocado quando ele primeiramente criado e todas configuracoes globais necessárias podem ser e e aconselhavel que seja feitas aqui.
  • onCreateView: Diferente da activity em que a interface gráfica é desenhada pelo setContentView(), o Fragment possui este método de callback que é responsável por desenha r e fazer o retorno da interface que pretendemos associar ao Fragment. Este método recebe 3 parâmetros: um LayoutInflater responsável por desenhar uma view, um ViewGroup como pai da view que vamos desenhar e um Bundle com o estado anterior.

Só com os dois métodos acima, já estamos prontos para utilizar os Fragments e vamos criar um gist como no seguinte gist do FragmentA e re-criar um segundo Fragment B.

Após criar os Fragments devemos colocar dentro de uma Activity e para tal existem duas formas de fazer isso:

  • Estaticamente: Colocar o fragment estaticamente dentro de uma Activity é feito declarando o Fragment directamente no ficheiro xml do layout assim como declaramos um TextView, Button ou EditText. O colocar o Fragment desta maneira ele ficara ligado aquela Activity para sempre e não poderá ser modificado durante a execução da aplicação. Um exemplo muito pratico da utilidade deste método e para criar interfaces com dois painéis em um única Activity como vimos acima. O exemplo desta técnica encontra-se AQUI
  • Dinamicamente: Colocar os fragments dinamicamente uma das formas mais utilizadas pelo simples facto de poder-se adicionar, alterar ou remover um Fragment de uma Activity enquanto executamos a aplicação. Esta técnica é muito utilizada quando se usa Navigation Drawer(menu de navegação lateral) e ao seleccionar em cada opção aparentemente parece ser uma outra Activity já que a interface gráfica vai mudando mas é na verdade uma troca de Fragments. Aqui  não é o Fragment que é directamente colocado no ficheiro de xml mas sim um FrameLayout que servira de contentor para colocar os Fragments dinamicamente com no gist.

Os ficheiros xml mencionados nas duas técnicas acima tem de ter o mesmo nome e são colocados em pastas devidamente especificadas para que ao executar a aplicação, dependendo do dispositivo e das configurações o android saiba para que pasta recorrer e buscar os ficheiros que precisa. Para o caso em que estamos a trabalhar, devemos colocar o ficheiro xml com  o Framelayout dentro da pasta res->layout e o outro com os dois Fragments definidos estaticamente na pasta layout-sw600 que significa que sera apenas carregado quando o tamano mínimo da tela seja de 600 dp. Para mais informações sobre como organizar os recursos em pastas veja AQUI.

O código da MainActivity esta escrito de tal forma que ao executar a aplicação, durante o onCreate da Activity e primeiramente feito o setContentView e apontamos para o ficheiro xml mencionado acima. De seguida mapeamos o FrameLayout utilizando o id definido em um dos ficheiros xml. Se o utilizador estiver a utilizar um tablet, porque não existe especificado um FrameLayout no ficheiro de layout, teremos a variável com um valor nulo e podemos criar um novo caminho para o código que sera executado no modo do tablet e os Fragments definidos estaticamente estarão la. Caso a variável  do FrameLayout não seja nula significa que estamos a utilizar um smartphone e teremos que colocar o fragment dentro do nosso frameLayout como no seguinte gist.

Espero que depois deste post, tenhamos aprendido um pouco sobre Fragments  e como podemos os utilizar para criar interfaces graficas mais ricas e dinamicas….

Como sempre fico a espera pelos comentários, criticas e um feedback acerca do que pode ser melhorado!

Obrigado Ate a proxima