Caso prefira, você encontrará todo esse material, em inglês, no site do Developer Android. A tradução e comentários dos materiais eu faço livremente para ajudar a comunidade que fala português.

sexta-feira, 25 de fevereiro de 2011

0 comentários

Interface de Usuário - Usando o Eclipse para criar as interfaces

Alguém pode dizer que não gosta de criar interfaces usando XML diretamente. Declarar as estruturas pode, realmente, ser algo bastante tedioso e, por que não dizer, complexo. Se você esquecer uma estrutura, o XML pode ficar corrompido e, dependendo do quão experiente você é usando essa tecnologia, será complicado achar onde está o erro.

Então, como usar o Eclipse para editar o XML? Basta procurar pelo arquivo main.xml no seu projeto e abrí-lo.


Abaixo da janela, você perceberá que existem duas abas: Graphical Layout e main.xml. A aba main.xml estará aberta por padrão. 



 Clique na aba Graphical Layout para ver uma tela como a seguinte.


Na tela, do lado esquerdo, está a paleta de widgets que você poderá inserir nos diversos layouts mostrados também na imagem.


As configurações estão todas na tela. Você poderá, por exemplo, escolher o tamanho da tela. Veja que já existe a versão de 10.1 in WXGA, para que possa criar apps para o Honeycomb. Tenha a certeza de estar numa tela grande para que possa visualizar toda a tela, caso altere para ela.


 Além disso, você poderá escolher se quer criar o layout em modo portrait ou landscape.


Você ainda pode escolher para que tipo de Android está criando o arquivo layout XML. Dependendo da versão que estiver selecionada, controles aparecerão ou não.


Algumas telas com as opções da paleta estão mostradas acima.



Acima você pode ver que, dependendo da versão do Android que está selecionada, os componentes se mostram de maneira diferente na tela.



Todos os widgets tem opções de contexto que podem ser acessadas com o botão direito do mouse. Mesmo tendo todas as opções a um click de distância, vale a pena ler a documentação oficial do Android para que saiba como fazer ajustes finos, que não poderão ser efetuados pelo editor.

Essa opção do Eclipse só visa facilitar a criação das interfaces, mas o ajuste fino, como disse, deve fazer parte do arsenal do desenvolvedor, afim de obter o melhor layout possível.

Muito mais fácil criar interfaces assim, não?

Interface de Usuário - Declarando o Layout

Antes de começar, havia prometido que iria falar de storyBoard. E ainda vou. O caso é que estou no notebook e não tenho um software aqui para desenhar o storyboard, como o Corel. Na verdade, eu desenho o storyboard numa folha de papel mesmo, mas para efeito do blog, quero desenhá-lo em alguma ferramenta. Ou, dependendo, faço no papel e scanneio, não sei ainda. De qualquer forma, volto a esse assunto em breve.

Seu layout é a arquitetura da interface de usuário em uma atividade. Ele define a estrutura de layout e guarda os elementos que aparecem para o usuário. Você pode declarar seu layout de duas maneiras:

  • Declarando os elementos de interface em XML. O Android provê um vocabulário XML fácil que corresponde à classe View e subclasses como widgets e layouts.
  • Instanciar elementos de layout em tempo de execução. Sua aplicação pode criar os objetos View e ViewGroup (e manipular suas propriedades) programaticamente.

A framework Android dá a você a flexibilidade de usar ou um deles ou ambos os métodos de declaração e gerenciamento de sua interface de aplicação. Por exemplo, você poderia declarar seu layout de aplicação em XML, incluindo os elementos de tela que vão aparecer neles e suas propriedades. Você poderia então adicionar código em sua aplicação que modificaria o estado dos objetos de tela, incluindo aqueles declarados em XML, em tempo de execução.

A vantagem de declarar a interface em XML é que ela permite a você uma melhor separação da apresentação da sua aplicação do código que controla seu comportamento. As descrições da interface são externas ao seu código de aplicação, o que significa que você pode modificá-lo ou adaptá-lo sem ter de modificar o código fonte e recompilar. Por exemplo, você pode criar layouts XML para orientações diferentes, para diferentes tamanhos de tela e diferentes linguas. Adicionalmente, declarando o layout em XML faz ser mais fácil visualizar a estrutura de sua interface, então é mais fácil debugar problemas.

Em geral, o vocabulário XML para declaração de elementos de interface segue a estrutura e nomeação de classes e métodos, onde os nomes de elementos correspondem aos nomes de classe e nomes de atributos para métodos. De fato, a correspondencia é, na maioria das vezes, tão direta que você pode entender que atributo XML corresponde ao método de classe, ou inquirir qual classe corresponde ao elemento xml dado. Contudo, note que nem todo vocabulário é identico. Em alguns casos, existem diferenças mínimas na nomeação dos atributos e métodos. Por exemplo, o elemento EditText tem um atributo text que corresponde a EditText.setText().

Objetos de Layout Comuns

Os tipos de layout mais comuns são:

FrameLayout

É o mais simples dos tipos de objeto de layout. É basicamente um espaço em branco na tela que você pode preencher com um objeto - por exemplo, uma foto que você quer que seja mostrada. Todos os elementos filhos de um FrameLayout são inseridos no canto esquerdo superior da tela; você não pode especificar uma localização diferente para a view filha. Views filhas subsequentes serão simplesmente desenhadas sobre as views anteriores, particalmente ou totalmente obscurescendo-as (a não ser que o novo objeto seja transparente).

Abaixo um código com FrameLayout


<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
android:id="@+id/frameLayout1" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView 
    android:text="Eu sou um TextView" 
    android:id="@+id/textView1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
    </TextView>
    
</FrameLayout>


E o resultado:


Agora outro código com FrameLayout mas com dois componentes dentro do Layout:


<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout 
android:id="@+id/frameLayout1" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
xmlns:android="http://schemas.android.com/apk/res/android">
    <TextView 
    android:text="Eu sou um TextView" 
    android:id="@+id/textView1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
    </TextView>
    <Button 
    android:text=".." 
    android:id="@+id/button1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
    </Button>
    
</FrameLayout>


E o resultado:


Perceba que o botão ficará por cima do TextView. Como dito acima, o componente subsequente (Button) será desenhado sobre o componente que já existe (TextView).

LinearLayout

Esse layout alinha todos os componentes filhos em uma única direção - verticalmente ou horizontalmente, dependendo em como você define o atributo orientation. Todos os filhos - entenda filho como cada um dos elementos dentro de um layout - são mostrados um após o outro, então uma lista vertical terá apenas um filho por linha, não importa o quão larga a tela seja, e uma lista horizontal vai mostrar uma única linha (com a altura baseada no filho mais alto). Um layout linear respeita as margens entre os filhos e o atributo gravity (alinhamento right, center ou left) de cada filho.

O layout linear também suporta um peso (weight) para cada filho individual. Esse atributo assinala um valor de "importância" para uma view e permite que seja expandida para preencher quaisquer espaços remanescentes na view pai. Views filhas podem especificar um valor de peso baseado num integer e então qualquer espaço remanescente na viewGroup é assinalado ao filho na proporção do peso declarado. O peso padrão é zero.

Difícil entender, né? Nem tanto. Por exemplo, se existem três text boxes e dois deles declaram um peso de 1, enquanto ao outro é dado peso de 0, o terceiro textbox sem um peso não vai crescer e vai apenas ocupar a área ocupada pelo seu conteúdo. Os outros text boxes vão igualmente preencher o espaço remanescente. Se o terceiro textbox é dado um peso de 2 ao invés de 0, então ele é declarado como mais importante que os outros dois text boxes e então ele terá metade do total do espaço da tela, enquanto os outros compartilham a outra metade da tela em iguais pedaços.

Basicamente esse sistema de pesos permite que você possa dividir o espaço da tela. No exemplo acima, havendo dois text boxes com peso 1 e um com peso 0, o que o sistema Android fará é o seguinte: ele pegará o textbox sem peso e calculará o espaço que ele ocupará na tela, de acordo com o seu conteúdo. Digamos que o conteúdo ocupe 10% da tela. Os outros dois text boxes terão 90% da tela para dividir entre si. Como ambas têm peso 1, ambas receberão 45% do restante da tela.

Mas, tendo o terceiro textbox peso 2 e os dois primeiros peso 1, fica mais fácil calcular. Basta somar os pesos de todos os componentes, que totalizam, nesse caso, 4. Como o terceiro textbox tem peso 2, ele terá 50% da tela. Os outros dois text boxes, portanto, terão 25% da tela.

Ou seja, colocando pesos nos componentes ficar mais fácil calcular a divisão na tela.

Abaixo um código usando linearLayout


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
android:id="@+id/frameLayout1" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView 
    android:text="Eu sou um TextView" 
    android:id="@+id/textView1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
    </TextView>
    <Button 
    android:text=".." 
    android:id="@+id/button1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
    </Button>
    
</LinearLayout>


E o resultado:


Perceba como os componentes estão um abaixo do outro, dado que a orientação é vertical no código acima.

TableLayout

Esse layout posiciona seus filhos em linhas e colunas. Os conteiners do TableLayout não mostram bordas para linhas, colunas ou células. As tabelas podem conter quantas colunas, linhas ou células você quiser. No entanto, as células não permitem usar a propriedade span, como acontece em HTML.

Objetos TableRow são as views filhas de uma TableLayout (cada TableRow define uma linha na tabela). Cada linha tem zero ou mais células, onde cada uma delas é dada por um tipo de view diferente (TextView ou ImageView, por exemplo). Uma célula ser um objeto ViewGroup, onde você poderá aninhar outra TableLayout como uma célula.

Eu disse anteriormente que apenas um tipo de Layout poderia ser colocada numa View. E é isso mesmo. Apenas um tipo de Layout pode ser colocado numa view. Se dois TableLayouts, por exemplo, estiverem numa view, elas obrigatoriamente virão uma aninhada à outra.

Você pode colocar o seguinte código que funcionará:


<?xml version="1.0" encoding="utf-8"?>
<TableLayout 
    android:id="@+id/tableLayout1" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android">
   
        <TableLayout 
        android:id="@+id/tableLayout2" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content">
        </TableLayout>
        
</TableLayout>


Mas se eu colocar um código assim:


<?xml version="1.0" encoding="utf-8"?>
<TableLayout 
android:id="@+id/tableLayout1" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
xmlns:android="http://schemas.android.com/apk/res/android">   
</TableLayout>
<TableLayout 
android:id="@+id/tableLayout2" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content">
</TableLayout>


Eu terei o seguinte erro:


Veja o seguinte código abaixo:


<?xml version="1.0" encoding="utf-8"?>
<TableLayout 
android:id="@+id/tableLayout1" 
android:layout_width="fill_parent" 
android:layout_height="fill_parent" 
xmlns:android="http://schemas.android.com/apk/res/android">
    <TableRow 
    android:id="@+id/tableRow1" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
        
        <TextView 
        android:text="TextView1"
        android:padding="3dip" />        
        <TextView 
        android:text="TextView2" 
        android:gravity="right"
        android:padding="3dip" />
        
    </TableRow>
    <TableRow 
       android:id="@+id/tableRow2" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content">
    
        <TextView 
        android:text="TextView3" 
        android:padding="3dip" />
        <TextView 
        android:text="TextView4" 
        android:gravity="right"
        android:padding="3dip" />
           
    </TableRow>
  
</TableLayout>


E o resultado:



RelativeLayout

Esse tipo de layout permite aos filhos especificar posições relativas à visão pai ou relativa a outro elemento (especificado pelo ID). Então você pode alinhar dois elementos pela borda direita, ou fazer um atrás do outro, centralizado na tela, centralizado à esquerda e assim por diante. Elementos são renderizado a partir do primeiro elemento. Então, se esse elemento está alinhado ao centro da tela, os outros elementos alinham-se a esse elemento relativo ao centro da tela. Ainda mais, por conta dessa ordenação, se você estiver usando XML para especificar o layout, o elemento que você referenciar (para que possa posicionar os outros elementos) deve ser listado no XML antes de ser referido em outras views.

Veja o código abaixo:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="fill_parent" 
                android:layout_height="wrap_content"
                android:padding="10px" > 
    <TextView android:id="@+id/label" 
              android:layout_width="fill_parent" 
              android:layout_height="wrap_content" 
              android:text="Type here:" />
    <EditText android:id="@+id/entry" 
              android:layout_width="fill_parent" 
              android:layout_height="wrap_content" 
              android:layout_below="@id/label" />  
    <Button android:id="@+id/ok" 
            android:layout_width="wrap_content" 
            android:layout_height="wrap_content" 
            android:layout_below="@id/entry"
            android:layout_alignParentRight="true"
            android:layout_marginLeft="10px"
            android:text="OK" />
    <Button android:layout_width="wrap_content" 
            android:layout_height="wrap_content"
            android:layout_toLeftOf="@id/ok"
            android:layout_alignTop="@id/ok"
            android:text="Cancel" /> 
</RelativeLayout>


E o resultado



Veja que o alinhamento dos elementos é dado em funcção das configurações como _alignParentRight, _toLeftOf, etc.

Ok. Eu já sei como são os layouts. E ai?

Agora você tem de escrever o XML na pasta res/layout. Basta isso para criar a interface. Simples, não?

Carregando o recurso XML

Quando você compila a aplicação, cada layout XML é complicado em um recurso View. Você deverá carregar o recurso layout a partir do código da aplicação, em sua implementação Activity.onCreate(). Faça isso chamando setContentView(), passando a sua referencia para o recurso de layout na forma de R.layout.nome_do_layout. Por exemplo, se o seu layout é chamado de main.xml, você deverá carregar a sua atividade tal como abaixo:
    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);    }
Quando você chama setContentView() passando uma referência de recurso de layout, a atividade infla o recurso na tela e a tela pode, então, ser desenhada pelo sistema Android.

Bem, por enquanto é isso. No próximo post eu falarei como desenhar as telas usando o Eclipse.

Interface de usuário - Parte 2

No post passado falei um pouco sobre as interfaces e agora dou continuidade a esse assunto tão importante. Falei das Views e ViewGroup, da hierarquia das Views, dos Layouts e Widgets. Obviamente vou voltar a cada um deles com maior detalhe. Vou apenas terminar a introdução nesse post e retornar a cada um deles.

Eventos de Interface

Uma vez que você coloca os widgets dentro dos layouts nas interfaces que vai montar, provavelmente vai querer saber sobre a interação do usuário com eles, para que assim possa chamar ações. Para ser informado dos eventos de interface, você precisa fazer uma de duas coisas:

  • Definir um event listener e registrá-lo com a View. Mais frequentemente do que podemos pensar, essa é a maneira como você vai interceptar os eventos. A classe View contém uma coleção de interfaces aninhadas chamadas On<AlgumaCoisa>Listener, cada um com o método callback chamado On<AlgumaCoisa>(). Por exemplo, View.OnClickListener (para que possa ser interceptados os clicks em uma View), View.OnTouchListener (para interceptar os eventos touch screen na View) e View.OnKeyListener (para interceptar teclas que sejam pressionadas no dispositivo). Se você quer que sua View seja notificada quando ouver um click (como um botão sendo pressionado), implemente o OnClickListener e defina o método callback OnClick e o registre para a View com setOnClickListener().
  • Fazer um override de um método callback para a View. Isso é o que você pode fazer quando você implementou sua própria View class e quer escutar eventos específicos que ocorrem dentro dele. Eventos de exemplo que você pode interceptar é quando a tela é tocada (onTouchScreen()), quando o trackball é movido (onTrackballEvent()), ou quando uma tecla é pressionada (onKeyDown()). Isso permite que você defina o comportamento padrão de cada evento dentro da View customizada e determinar se o evendo deverá ser passado para alguma view filha. Veja bem, esses são callbacks da classe view e portanto você só poderá definí-las quando você cria um componente customizado.
Menus

Menus de aplicação são outra parte importante da interface da aplicação. Menus oferecem uma interface confiável que revela funções da aplicação e configurações. A mais comum aplicação de menu é revelada pressionando o botão MENU do dispositivo. Contudo, você pode criar menus de contexto, que podem ser revelados quando o usuário pressiona um botão no dispositivo.

Essa é, na minha opinião, uma das coisas mais interessantes quando se programa para o Android. Quando se programa para o iOS, da Apple, você tem de deixar todas as opções de acesso a menus e outras configurações sendo mostradas na tela, no formato de botões ou imagens. A razão disso é o formato minimalista dos gadgets da Apple, que têm apenas botão na parte posterior deles, o home button. Alguém poderá argumentar que é uma vantagem ter apenas um botão, principalmente para aqueles que entendem pouco de informática - como minha mãe, por exemplo, que usa um iPad tranquilamente mas não sabe para onde vai um PC.

Eu me sinto mais confortável tendo a possibilidade de usar menus de contexto, que retornam opções relativas à aplicação que está sendo executada no momento. É uma vantagem quando se pensa que o aplicativo criado para Android poderá ter uma interface ainda mais minimalista, já que não precisará de um botão dentro do app para acessar suas configurações, diferente dos apps para o iOS. A desvantagem, no entanto, é que alguns usuários poderão demorar a se adaptar a uma interface desta. Como tudo na vida, há as vantagens e desvantagens. Mesmo assim, continuo achando que os benefícios são maiores que os malefícios.

Menus são também estruturados usando a hierarquia da View, mas você não define essa hierarquia. Ao invés disso, você define os métodos de callback onCreateOptionsMenu() ou onCreateContextMenu() para a sua atividade e declara os itens que quer incluir em seu menu. No momento apropriado, o Android vai automaticamente criar a hierarquia de view necessária para que o menu e para que ele seja desenhado com seus itens posicionados.

Menus podem interceptar seus próprios eventos, então não há a necessidade de registrar listeners de eventos nos itens de seu menu. Quando um item de seu menu é selecioinado, os métodos onOptionsItemSelected() ou onContextItemSelected() serão chamados pelo framework.

E, como seu layout de aplicação, você tem a opção de declarar os itens de seus menus em um arquivo XML.

Então, é só isso?

Não, isso é apenas o pontapé inicial. Ainda temos os Adapters e os Estilos e Temas, que só abordaremos quando necessário.

Por hora, basta dizer que os adapters são conjunto de objetos que atuam como uma ponte entre os seus dados (que podem estar guardados em um arquivo XML ou outro tipo de media, como um banco de dados SQlite).

E os Estilos e temas são a maneira como você poderá customizar a aparência dos seus itens na tela. Não gosta do design de um botão? Modifique-o com os estilos e temas. Eles são recursos e, portanto, poderão ser reutilizados em qualquer parte da sua aplicação.

E agora? Quero mais, quero começar a criar minhas interfaces e começar a fazer meus projetos!

No próximo post, quero falar sobre algo chamado StoryBoard e de como podemos usar esse conceito para criar nossa aplicação e ter a exata noção de como tudo ficará ao final da programação.

quarta-feira, 23 de fevereiro de 2011

3 comentários

O que muda no ADT com o SDK 3.0 Honeycomb?

Bem, agora já temos como testar os projetos no Honeycomb, como se estivessemos no Xoom ou outro tablet que virá equipado com essa versão do Android, a 3.0. Se você for em Window > Android SDK and AVD Manager, poderá criar um novo AVD.

Como no post sobre como configurar um AVD, Android Virtual Device, agora temos como configurá-lo para abrir na versão 3.0. Como fazê-lo? É fácil:

  1. Aberto o Android SDK e AVD Manager, insira o nome. Eu coloquei MotorolaXoom como o nome, mas você pode escolher o nome que quiser, desde que seja escrito sem espaços, e escolha Android 3.0 - API Level 11
  2. A tela de seleção do AVD deve ficar como abaixo:
  3. Perceba que a configuração da tela é WXGA, que consiste numa resolução de 1280x768. Ou seja, o emulador vai abrir uma tela com essa resolução. Se você estiver usando um notebook de resolução semelhante ou mesmo menor, vai acontecer do emulador abrir na tela e você não ter acesso à totalidade do emulador. Nesse caso, o ideal é ir para um outro PC cuja tela tenha resolução maior.
  4. Criado o AVD, ele deverá aparecer assim na tela do Android SDK and AVD Manager:
  5. Ao rodar alguma aplicação criada para o SDK 3.0, basta clicar na opção como mostrada abaixo e escolher Run Configurations...
  6. Por fim, a tela abaixo aparecerá. Vá até a guia Target e marque o AVD do MotorolaXoom e, finalmente, clique no botão Run. Se tudo correr bem, a tela do emulador será carregada e você estará dentro do Honeycomb, podendo testar sua aplicação.
Só não coloquei a tela do honeycomb rodando pois meu notebook tem uma resolução semelhante à WXGA. Por isso, o emulador ficou tomando a tela mas não pude ver todas as opções. Assim que o fizer no meu outro PC, esse sim com uma tela de resolução um pouco maior, eu coloco a tela do Honeycomb.

E, claro, não me esqueci que tenho de continuar a falar de interfaces. É que essa coisa de atualizar para o SDK 3.0 me deixou muito feliz! Finalmente poderemos criar softwares para o sistema de tablets que, eu entendo, deixa o iOS no chinelo, hehehe.


UPDATE 01

Fiz a instalação do zero novamente apenas para ver se estava tudo bem, dessa vez usando o installer_r10-windows.exe que se encontra no site do Android.

Por algum motivo, o instalador não estava conseguindo enxergar que eu tinha o JDK instalado no meu PC. O que eu fiz foi o seguinte: eu coloquei o caminho dentro da variável PATH do sistema operacional apontando para a pasta C:\Program Files\Java\jdk1.6.0_24 (pasta da instalação do meu JDK. Se você apontou para outro local, basta apontar para o local correto onde o seu Java foi instalado).



UPDATE 02

Olha só a cara do Honeycomb rodando no meu PC no emulador! Fantástico, não?

Tela inicial do emulador do Honeycomb

Home Screen

Arrastando o cadeado até o local para abrir o "tablet"

Olha ai o "Hello, World" rodando no Honeycomb!

Tela inicial dentro do Tablet

Todos os apps (o Hello World está lá no meio)

Meus apps

Mostrando quais apps estão rodando

Agora, querem uma notícia boa e uma ruim? A boa é que a emulação é show de bola! A ruim é que é necessário uma máquina com uma excelente configuração para rodar tranquilamente. Aqui tenho um Intel Core 2 Duo T7500 com 4Gb de RAM e rodou muito lento. Imaginem em configurações mais modestas que a minha... Eu entendo que seria necessário pelo menos um Core 2 Quad com uns 8Gb de RAM para aguentar o tranco tranquilamente. Ou então, valeria mais a pena economizar e debbugar no próprio Xoom, só para citar o exemplo do tablet mais em evidência que rodará o Honeycomb. O que me leva à seguinte questão: quanto custará o Xoom no Brasil?

UPDATE 03

Preço do Motorola Xoom: US$ 799 com 3G (que poderá ser, no futuro, usado na rede 4G) e US$ 600 na versão Wi-Fi. Sério, MUITO caro! Obviamente, se comparado ao iPad, que custa US$ 499 na versão Wi-Fi, tá no preço. O ponto a favor do Xoom é que ele tem 32Gb de espaço interno, enquanto que o iPad começa apenas com 16Gb.

Mesmo assim, com o preço do iPad pelas vias oficiais em R$ 1645,00, imaginem o preço do Xoom por aqui? Se for feita a relação direta, será coisa de R$ 1975. Mas eu entendo que, sendo no Brasil, o preço vai beirar os R$ 2.500,00 brincando. É isso ai, começarei a economizar desde já.

UPDATE 04

O leitor Ricardo disse que fez a instalação do ADT no Eclipse Galileu. Resolvi testar e fiz a instalação no Eclipse Helios e, aparentemente, tudo correu bem. Mesmo assim, vou manter o uso apenas da versão Classic do Eclipse para efeito de mostrar como programar para o Android nesse blog.

Usando o Eclipse pós atualização SDK 3.0 Honeycomb

Após a instalação dos arquivos do SDK 3.0 Honeycomb a partir do SDK Manager, é necessário fazer a atualização do ADT Plugin dentro do Eclipse. Para fazer a atualização você já deverá ter o ADT instalado no Eclipse. Se não instalou o ADT, vá nesse link para fazê-lo. Para atualizar a partir do ADT 0.9.9, siga as instruções abaixo:
  1. Abra o Eclipse. Uma tela como a seguinte deverá aparecer
  2. Vá até Help > Install New Software
  3. Escolha, entre as opções, a que tem o ADT, como na imagem abaixo
  4. Ao escolher a opção do ADT Plugin, o Eclipse acessará a internet para verificar as atualizações disponíveis. Ao aparecer as opções, como na imagem abaixo, e clique em Next.
  5. Em algum momento uma tela como a de baixo aparecerá, pedindo que seja confirmada a instalação. Prossiga marcando a opção como mostrada na imagem e depois clicando em Finish.
  6. Ao terminar de baixar os arquivos, o Eclipse dirá que a instalação pode ser perigosa. Aceite, sem medo, já que os arquivos vieram dos servidores da Google.
  7. Por fim, o Eclipse pedirá para ser reinicializado. Prossiga com a reinicialização.

terça-feira, 22 de fevereiro de 2011

2 comentários

URGENTE: SDK 3.0 para Honeycomb finalizado e disponível


Acabei de ver no meu timeline no Twitter (@celeiroandroid) que o SDK 3.0 para Honeycomb está finalizado e disponível para download. Na mesma hora entrei no SDK Manager (Iniciar > Android SDK Tools > SDK Manager). Se estiver no Windows Vista ou Windows 7, abra o SDK Manager como Administrador, clicando com o botão direito e escolhendo essa opção. Ao abrir, ele faz uma pesquisa na internet pelos novos pacotes e, olha só, não é que está disponível mesmo?


Pelo que li no blog AndroidCentral, a Google lançou o SDK para estar em sintonia com o lançamento do Motorola Xoom, que vem com o Honeycomb (cujo vídeo você pode ver aqui). Ou seja, os desenvolvedores já poderão começar a se preparar para essa nova versão desse sistema operacional incrível que é o Android!

Pelo que entendo, não é necessário fazer nada além de baixar os novos pacotes. Em todo o caso, assim que terminar de baixá-los, coloco aqui quaisquer problemas (e soluções) para a instalação e atualização do ADT (que antes estava na versão 9.0 e agora foi para a 10.0).

Volto em breve com novidades.

UPDATE 01 - Olha só que diz as notas de versão do Honeycomb (tradução livre):

Plataforma Android 3.0
API Level: 11

Para desenvolvedores, a plataforma Android 3.0 está disponível como um componente que pode ser baixado para o SDK Android. A plataforma que pode ser baixada inclui a biblioteca Android e imagem de sistema, assim como um conjunto de skins de emulador e mais. A plataforma não inclui nenhuma biblioteca externa.

Para iniciar o desenvolvimento e testes no Android 3.0, use o Android SDK Manager para fazer o download da plataforma dentro do SDK. Para mais informações, veja o link Adicionando Componentes SDK. Se você é novo no Android, faça o download do SDK Starter Package primeiro.

Para uma introdução aos pontos altos do Android 3.0, veja o link.

Nota: Se você já publicou uma aplicação Android, por favor teste e faça a otimização da sua aplicação Android 3.0 o mais rápido possível. Você deverá ter a certeza que sua aplicação provê a melhor experiência possível nos dispositivos com a versão mais nova do Android. Para mais informações sobre o que você pode fazer, leia Otimizando Apps para Android 3.0

UPDATE 02 

Baixei as atualizações mas não consegui baixar todas. Baixou 3 de 5. O que o SDK Manager me informou foi que para instalar a primeira das atualizações era necessário uma atualização que ainda não estava presente no sistema. Essa atualização foi instalada em uma das três que foram baixadas. Espero que agora tudo transcorra tranquilo e os outros pacotes sejam atualizados tranquilamente.

UPDATE 03

Enquanto as atualizações seguem, veja só as mudanças do ADT 10.0.0:

Dependencias: O ADT 10.0.0 foi feito para ser usado no SDK Tools r10. Se você não instalou o SDK Tools r10 no seu SDK, use o Android SDK e AVD Manager para fazê-lo.

Notas gerais:
  • As ferramentas agora automaticamente geram código fonte em linguagem de programação Java (dentro da pasta gen) e bytecode (na pasta res/raw) diretamente a partir dos seus arquivos .rs
  • Um editor XML binário foi adicionado.
  • O Traceview agora está integrado à interface do Eclipse.
  • A opção "Go To Declaration" para arquivos XML e .java rapidamente mostram todas as entradas encontradas no projeto e permitem pular para itens específicos como traduções de strins e handlers onClick.
  • Melhorias no editor visual de layout:
    • Uma nova paleta de categorias e previews de renderização
    • Uma barra de ações de layout que provê rápido acesso às operações comuns de layout
    • Quando a biblioteca de renderização do Android 3.0 é selecionada, layouts renderizam mais como nos dispositivos (i.e. smartphones ou tablets). Isso inclui renderização de status e barras de títulos para mais fielmente refletir os espaços de tela disponíveis para aplicações.
    • Melhorias no zoom como Fit to View, Persistent Scale e acesso ao teclado.
    • Mais melhorias para os layouts <merge>, assim como layouts com overlays de gestos.
    • Melhorias na renderização de erros de diagnósticos.
É, esse ADT vem para arrebentar mesmo! E arrebentar num bom sentido! Hehehehe

UPDATE 04

Erro ao tentar baixar o Android SDK Tools, revision 10. Veja só o erro que deu...

Downloading Android SDK Tools, revision 10
Installing Android SDK Tools, revision 10
[post_tools_install.bat] Updating SDK Manager.exe
[post_tools_install.bat] Error: O arquivo já está sendo usado por outro processo.
[post_tools_install.bat]         0 arquivo(s) copiado(s).

Vou esperar terminar o outro update para tentar novamente para ver se funcionará corretamente dessa vez. Pode ser que seja necessário atualizar para o SDK Manager r10. Vamos ver...

UPDATE 05

Apesar do erro acima, ele fez a atualização do SDK Manager r09 que eu estava usando para a versão r10, como mostrado na imagem abaixo:


Só que agora, olha só a quantidade de atualizações que ainda me restam baixar:


Detalhe, olha só um pacote que é para o GALAXY Tab da Samsung! Bacana né?

UPDATE 06

Downloads terminados. Vou testar mais tarde no Eclipse para ver as mudanças e dou o parecer por aqui.

Uma palavra sobre a ordem dos conteúdos sobre o Android

Antes de mais nada, gostaria de pedir desculpas. Esse post não era para falar sobre esse assunto. Era para dar continuidade ao post anterior, que fala sobre interfaces. No entanto, achei relevante e resolvi fazer uma espécie de parada rápida e discutir um assunto que veio ao meu encontro hoje.

O caso é que estava conversando com um amigo meu que também está interessado em programação para Android e que está acompanhando esse blog. Ele me fez uma pergunta que não havia me ocorrido antes. Apesar deu gostar de colocar as coisas de maneira bastante didática, ele me perguntou como seria a ordem dos conteúdos sobre o Android.

Basicamente o que ele quis dizer foi como será o conteúdo programático, por assim dizer?

Eu realmente não havia pensado nisso, já que minha intenção era somente a de ir colocando todos os conhecimentos que ia adquirindo lendo os diversos livros de Android que tenho (e alguns outros que comprei que vou deixar os links daqui a pouco) e ir seguindo uma sequência que me parecesse lógica, ainda que não houvesse uma ordem pré-estabelecida.

Mas depois de perceber que realmente o meu blog tem esse objetivo, de começar do básico mesmo e ir avançando até a criação de apps para o Market do Android, eu resolvi fazer uma pequena pesquisa para me guiar e ajudar quem está vindo a esse blog pela primeira vez a não se perder na quantidade de materiais que existem por aqui.

Posto isso, vou listar abaixo os novos livros que comprei de Android, sendo o último da lista abaixo (o da Wrox) o melhor dos que já vi. Se querem um excelente livro, comprem esse ao invés de qualquer outro.
E, os livros que já havia indicado aqui vão abaixo, novamente:

Me ocorreu também, em conversa com esse meu amigo, que algum de vocês podem não saber Java. E, não sabendo Java, como vão programar para Android? Eu andei pesquisando e vi que na internet existem inúmeros tutoriais de Java. No entanto, eu sempre achei que livros são a melhor fonte de informação quando se quer realmente aprender a fundo alguma tecnologia. E o melhor livro que eu vi (que ainda não comprei) é esse abaixo.
E quanto ao conteúdo programático?

Como eu também comecei a programar para Android tem pouco tempo, não tenho um conteúdo programático que possa ser chamado de excelente. No entanto, no livro da Wrox há uma sequência que acho bastante razoável.
  1. Hello, Android.
  2. Iniciando no Android (configuração e instalação dos pré-requisitos e softwares)
  3. Criando aplicações e atividades
  4. Criando interfaces de usuário
  5. Intents, Broadcast Receivers, Adapters e a internet
  6. Arquivos, salvando o estado e preferências
  7. Bancos de dados e content providers
  8. Mapas, geocoding e serviços baseados em localização
  9. Trabalhando em background
  10. Audio, video e uso da câmera
  11. Telefonia e SMS
  12. Bluetooth, redes e wi-fi
  13. Sensores
Só que essa ordem que eles colocaram no livro para os conteúdos só tem um pequeno erro, na minha humilde opinião: a criação de interfaces de usuário deve ser discutida antes da criação das aplicações e atividades. Ainda que eu tenha falado das atividades (bem rapidamente) antes da criação das interfaces nesse blog, em todas as outras programações que uso (VB.Net, C# e Java) sempre começamos mostrando os componentes de como criar a interface.

E essa é uma boa tática: sabendo como a tela vai ser composta faz com que o entendimento de como se programar para uma linguagem se torne mais fácil, dado que podemos imaginar como a tela vai ficar e, de fato, saber como vamos montá-la.

Só que existem ainda outros pontos interessantes além do que foi colocado acima:
  1. Como compilar código nativo em Android?
  2. Como criar jogos em java desde o início?
  3. O que são poligonos (e a razão deles serem tão importantes para os jogos)?
  4. Como criar gráficos 2D?
  5. Como criar gráficos 3D?
Com tudo isso a abordar, é de se esperar então que a uma ordem seja estabelecida, para que não nos percamos. Então, a ordem dos assuntos que vou abordar será a seguinte:

  1. Visão geral do Android (que já cobri)
  2. Criando interfaces de usuário (que estou cobrindo nesse momento)
  3. Atividades e Intents (coberto bem rapidamente também)
  4. Threads, Serviços, Receivers e Alerts
  5. Eventos de interface
  6. Técnicas de multimidia
  7. Interface de hardware
  8. Networking
  9. Métodos de data storage
  10. Serviços baseados em localização
  11. Desenvolvimento avançado em Android e;
  12. Debugging.
Acho que com isso todo mundo que acessa esse site terá um norte e saberá onde vamos chegar, ok?

Então, mãos à obra. No próximo post, como disse anteriormente, continuo falando de Interfaces.

Interface de usuário

Em uma aplicação Android, a interface do usuário é criada usando objetos View e ViewGroup. Existem muitos tipos de views e ViewsGroups, cada um deles descendente da classe View. Todas os controles de interface são descendentes de View, inclusive as classes de Layout. Só que as classes de Layout são extensões das ViewGroups.

Para quem já programa e quer entender o que são views, fique com o seguinte conceito em mente: as views estão para a programação em Android o que os forms são para outras linguagens. A maneira como os componentes são inseridos dentro da view é dado por um tipo de Layout .Cada view só poderá receber um tipo de Layout.

Os objetos View são as unidades básicas de interface de usuário na plataforma Android. A classe View serve como base para todas as subclasses, chamadas widgets, que implementam interface completa e funcional, como campos texto ou botões. As classes ViewGroup servem como base para as subclasses chamadas Layouts, que oferecem diferentes tipos de arquitetura de layout, como linear, tabular ou relativa.

Um objeto View é uma estrutura de dados cujas propriedades guardam os parâmetros de layout e conteúdo para uma área retangular da tela. Um objeto View gerencia suas medidas, layout, como é desenhado na tela, a mudança de foco, rolagem na tela e interações por gesto ou botão para a área onde ele reside. Como um objeto de uma interface de usuário, uma View é também um ponto de interação com o usuário e receber os eventos dessa interação e responde a eles.

Hierarquia das Views

Na plataforma Android, você define a interface da atividade usando uma hierarquia de View e ViewGroup, como mostrado no diagrama abaixo. A árvore de hierarquia pode ser simples ou complexa na medida que você necessita e você pode construir uma série de widgets e layouts predefinidos ou views customizadas.






Para anexar uma árvore hierárquica, como a que você vê acima, por exemplo, para ser renderizada na tela, sua atividade deve chamar o método setContentView() e passar uma referência para o nó raiz do objeto. O sistema Android recebe a referência e a usa para validar, medir e desenhar a árvore. O nó raiz da hierarquia faz uma requisição para que seus nós filhos se desenhem na tela. O nó filho ainda pode requisitar o tamanho e posicionamento do nó pai, mas o nó pai tem a decisão final do quão grande será cada filho. O Android desenha os elementos na ordem que eles foram feitos, mas sempre de cima para baixo, começando pelo nó pai e depois indo para os nós filhos.

E o que são os layouts?

Gerenciadores de Layout (ou Layout Managers) são extensões de uma classe ViewGroup usados para posicionar os controles filhos na interface que se quer criar. Você poderá colocar layouts dentro de outros layouts, mas isso não é recomendado. A sua interface, quando pensando em uso em smartphones, deverá ser a mais simples possível.

Algumas das mais versáteis classes de layout são:

  • FrameLayout - ViewGroup que permite inserir elementos na tela e eles vão sendo agrupados sempre alinhados no canto superior esquerdo da tela.
  • LinearLayout - ViewGroup que permite inserir elementos verticalmente ou horizontalmente. 
  • RelativeLayout - ViewGroup que permite que seus elementos filhos fiquem em posição relativa ao pai ou elementos irmãos.
  • TableLayout - ViewGroup que guarda os elementos internos em colunas e linhas, bem como em uma tabela HTML.

E o que inserir dentro desses layouts?

Os widgets. É isso que você deverá inserir dentro dos layouts. Os widgets são os elementos que vão criar a interface para que o usuário possa interagir com o seu aplicativo. Veja que há widgets que são os elementos de interface e os widgets que são os tipos de aplicativos que rodam na tela do smartphone para o qual se programa. São duas coisas diferentes.

Alguns controles familiares

  • TextView - Um campo de texto label, que pode ser multilinha, que possui formação de string e quebra automatica de linha. Não editável, apenas recebe informações que serão mostradas na tela.
  • EditText - Um campo editável, como um textbox. Aceita entrada de dados, multilinha e quebra de linha.
  • Spinner - É o dropbox ou combobox. O pessoal da Android resolveu mudar o nome. Mas o spinner é basicamente a mesma coisa. Ele têm esse nome pq na tela ele se assemelha com um cilindro que gira para que possa ser escolhida a opção.
  • Button - É o botão, que a gente já conhece tão bem.
  • CheckBox - Um botão que tem dois estados: marcado e não marcado.
  • RadioButton - Um botão que tem dois estados mas que vêm em grupo - somente uma das opções poderá ser marcada.
Existem ainda inúmeros outros tipos de controle, descritos aqui.

E como fazer a inserção desses widgets se eu não os conheço direito?

Se você estiver usando o plugin ADT, terá uma forma melhor de se desenhar os layout: visualmente. Para tal, abra o Eclipse e aponte para um projeto simples que você tenha criado. Basta abrir o arquivo main.xml que fica em res > layout.

Após isso, basta clicar em graphical layout e você terá uma lista dos componentes que poderão ser inseridos na tela.



No próximo post continuo a explicar sobre a interface de usuário.

*com conteúdo traduzido livremente do site do Android

segunda-feira, 21 de fevereiro de 2011

1 comentários

Ciclo de vida de uma aplicação Android

Visão geral de classe

Uma activity é uma tarefa, muito focada, do que um usuário pode fazer. Quase todas as atividades interagem com o usuário, então uma classe de atividade toma conta da criação de uma janela para você onde você poderá colocar todos os componentes de UI (User Interface) com o setContentView(view). Enquanto atividades são normalmente apresentadas para o usuário como telas full-screen, elas também podem ser apresentadas de outra maneira: como janelas flutuantes (através de um tema com windosIsFloating configurado) ou embutido dentro de outra atividade (usando ActivityGroup). Existem dois métodos que quase todas as subclasses de Activity vão implementar:

  • OnCreate(Bundle) é onde você inicializa sua atividade. Mais importante, aqui você vai usualmente chamar setContentView(int) com o recurso de layout definindo a sua interface, e usar findViewById(int) para retornar os widgets naquela interface que você que interagir programaticamente.
  • OnPause() é onde você lida com o usuário deixando a sua atividade. Mais importante, quaisquer mudanças feitas pelo usuário deverá, nesse ponto, ser efetivada (usualmente através do ContentProvider que guarda os seus dados).
Para que possa ser usado pelo Context.startActivity, todas as classes de atividade devem ter uma declaração <activity> no manifesto da sua aplicação em AndroidManifest.xml.

A classe Activity é a mais importante no ciclo de vida de uma aplicação e a forma como as atividades são lançadas e unidas é parte fundamental para a plataforma de modelo de aplicação. 

Ciclo de Vida

Atividades no sistema são gerenciadas como um activity stack, ou pilha de atividades em português. Quando uma atividade é iniciada, ela é colocada no topo da pilha e se torna a atividade corrente - a atividade anterior sempre permanece abaixo na pilha e não vai ser mostrada enquanto a atividade corrente não terminar.

Uma atividade tem quatro estados essenciais:

  • Se uma atividade está sendo executada e está sendo mostrada na tela (que é o topo da pilha), ela está em modo active ou running.
  • Se uma atividade perdeu o foco mas ainda assim está visível (ou seja, uma nova atividade está sendo mostrada na tela mas não ocupando-a completamente - atividades em janelas flutuantes, por exemplo, ela está em modo paused. Uma atividade em modo paused está completamente viva (ela mantém todos os estados e informações e mantém-se relacionada ao gerenciador de janelas), mas pode ser encerrado pelo sistema em situações de memória baixa extremas.
  • Se uma atividade é completamente obscurecida por outra atividade, ela está em modo stopped. Ela ainda retém o seu estado e informações, contudo não é mais visível pelo usuário e sua janela está escondida e pode acontecer de ser encerrada pelo sistema quando for necessário liberar memória.
  • Se uma atividade está em modo paused ou stopped, o sistema pode retirar a atividade da memória simplesmente pedindo a ela que seja finalizada ou simplesmente matando o seu processo. Quando é mostrada novamente ao usuário, ela terá de ser novamente reiniciada e restaurada para seu estado anterior.
O diagrama abaixo mostra os caminhos importantes de uma activity. Os retângulos representam chamadas a métodos que você pode implementar para realizar operações quando a atividade se mode entre os estados. Os retângulos com cantos arredondados são os estados principals que uma atividade pode ter.


Existem três laços que você pode achar interessante monitorar dentro de sua atividade:

  • O ciclo de vida completo de uma atividade acontece entre a primeira chamada do onCreate(Bundle) até o onDestroy(). Uma atividade vai fazer toda a configuração do estado "global" no onCreate() e liberar os recursos remanescentes em onDestroy(). Por exemplo, se você tem uma thread rodando em background para fazer o download de dados da rede, você deve criar essa thread em onCreate() e então pará-la em onDestroy().
  • O vida visível de uma atividade acontece entre o onStart até o onStop. Durante esse tempo o usuário pode ver a atividade na tela, apesar de às vezes não estar completamente visível ao usuário. Entre esses dois métodos você pode manter os recursos que são necessários para mostrar a atividade ao usuário. Por exemplo, você pode registrar um BroadcastReceiver no onStart() para monitorar as mudanças que impactam a interface. Os métodos onStart() e onStop() podem ser chamados múltiplas vezes enquanto a atividade se torna visível e escondida do usuário.
  • A vida na frente de tela de uma atividade (que é enquanto a atividade está visível completamente na tela do usuário), acontece entre onResume() até o onPause(). Durante esse tempo a atividade está na frente de outras atividades e interagindo com o usuário. Uma atividade pode frequentemente ir de status resumed para paused -- por exemplo, quando o smartphone ou dispositivo onde o app roda entrar em modo sleep - e por isso o código desses métodos deve ser mais simples.
O ciclo de vida de uma atividade é definida pelos métodos de atividade mostrados abaixo. Todos eles podem ser sobrescritos para fazer o trabalho apropriado quando um estado de atividade mude. Todas as atividades vão implementar onCreate(Bundle) para que as mudanças de dados sejam persistidas e, de outra maneira, preparar para encerrar a interação com o usuário. Voc}e pode sempre chamar a superclasse quando implementando um desses métodos.

 public class Activity extends ApplicationContext {

     protected void onCreate(Bundle savedInstanceState);
     protected void onStart();     
     protected void onRestart();
     protected void onResume();
     protected void onPause();
     protected void onStop();
     protected void onDestroy();

 }
 
Em geral, o movimento através do ciclo de vida das atividades se parece com o que vai abaixo:

MétodoDescriçãoPode ser morto?Próximo
onCreate()Chamado quando a atividade é criado. Aqui é quando você deve fazer todas as funções como: criar as views, linkar os dados às listas, etc. NãoonStart()
 onRestart()Chamado após a atividade ser parada e antes de ser reinciada. Sempre seguida por  onStart()NãoonStart()
onStart()Chamado quando a atividade se torna visível ao usuário. Seguido pelo onResume() se a atividade roda na frente ou por onStop() se ela se torna invisível.NãoonResume()ou onStop()
 onResume()Chamado quando a atividade vai iniciar a interação com o usuário. Nesse ponto, sua atividade está no topo da pilha de atividades e quaisquer dados que sejam inseridos serão feitos aqui. Sempre seguido pelo  onPause().NãoonPause()
onPause()Chamado quando o sistema está por resumir a atividade anterior. Isso é tipicamente usado para persistir quaisquer mudanças ainda não efetivadas, parar animações e oturas coisas que possam consumir a CPU, etc. Implementações desse método devem ser rápidos pois a próxima atividade não será mostrada até que esse método seja finalizado. Seguido por onResume() se a atividade retornar para a frente ou onStop() se ela se tornar invisível ao usuário.SimonResume()ou
onStop()
onStop()Chamado quando a atividade não mais estiver visível ao usuário, pois outra atividade foi resumida e está na frente desta. Isso pode acontecer porque outra atividade está sendo iniciada, uma atividade existende está sendo trazida para a frente ou essa atividade estiver sendo finalizada. Seguida pelo onRestart() se essa atividade está voltando para interagir com o usuário ou onDestroy() se a atividade estiver sendo encerrada.SimonRestart()ou
onDestroy()
onDestroy()A chamada final que você receberá antes que a atividade seja destruída ou finalizada. Isso pode acontecer porque a atividade está, de fato, sendo encerrada (alguém chamou finish() nela) ou porque o sistema está temporariamente destruindo a instância da atividade para aumentar o espaço na memória. Você pode distinguir entre esses cenários com o método isFinishing()Simnada

Note a coluna "pode ser morto". Para essas atividades que estão marcadas como tal, após o método retornar o processo que está sendo chamado, ela poderá ser morta pelo sistema em qualquer momento sem que outra linha de código precise ser executada. Por conta disso, é recomendável que seja usado o método onPause() para persistir dados em banco. Em adição a isso, o método onSaveInstanceState(Bundle) é chamado antes de colocar a atividade em background, permitindo que seja salvo quaisquer estados dinâmicos de instância de sua atividade, para que possa ser recuperada posteriormente em onCreate(Bundle), se a atividade precisar ser recriada. Note que é importante persistir dados no onPause ao invés do onSaveInstanceState(Bundle) já que   o método onSaveInstanceState não faz parte das chamadas do ciclo de vida e portanto não será chamada em todas as situações descritas na documentação.

Mudanças na configuração

Se a configuração de um dispositivo (como definido na classe Resources.Configuration) mudar, então qualquer coisa mostrando uma interface ao usuário deverá ser atualizada para ficar de acordo com as novas configurações. Já que a atividade é o mecanismo principal de interação com o usuário, ele inclui suporte especial para gerenciamento de mudanças de configurações.

A não ser que você especifique o contrário, uma mudança de configuração (como a mudança na orientação da tela, lingua, dispositivo de entrada - se teclado físico ou virtual, etc) vai causar a destruição da atividade corrente, indo através da atividade normal no ciclo de vida do processo em onPause(), onStop() e onDestroy(). Se a atividade está na tela do dispositivo, uma vez chamado o onDestroy(), a instância é destruída e uma nova instância da atividade é criada, com quaisquer estados que estavam na interface anterior restaurados na nova instância a partir do estado gerado pelo onSaveInstanceState(Bundle).

Isso é feito dessa maneira pois quaisquer recursos, sejam arquivos de layout, recursos de aplicação, etc, podem ser mudados baseados nos valores de configuração. Então, a única maneira segura de gerenciar uma mudança de configuração é retornar todos os recursos, incluindo layouts, imagens e strings. E já que as atividades já sabem como salvar seus estados e recriar-se a partir desses estados, essa é uma maneira conveniente de fazer com que a atividade seja reiniciada quando uma nova configuração é apresentada.

Salvando estados de persistência.

Existem dois tipos de persistência de estado que uma atividade por ter: dados compatilhados (tipicamente guardados em um banco de dados SQLite usando um content provider) e um estado interno como preferências de usuário.

Para dados de um content provider, sugerimos que as atividades usem um modelo de edição no local. Ou seja, quaisquer edições que o usuário faz são efetivados imediatamente no banco de dados sem requerer uma confirmação adicional. Suporte a esse modelo geralmente é simples e geralmente basta seguir as duas regras seguintes:

  • Quando criando um novo documento, a entrada do banco de dados, ou arquivo onde será gravado o dado, é criada automaticamente. Por exemplo, se um usuário escolhe escrever um novo email, uma nova entrada para o email é criado assim que ele começa a inserir dados. Assim, se ele for para outra atividade após esse ponto, o email aparecerá como rascunho.
  • Quando uma atividade está no método onPause(), ele deverá persistir para o banco de dados quando houve modificação de dados. Isso assegura que essas mudanças sejam vistas por quaisquer outras atividades que venham a ser executadas. Você vai, provavelmente, persistir seus dados mais agressivamente em momentos chaves durante o ciclo de vida da atividade: por exemplo, antes de iniciar uma atividade, antes de finalizar a sua atividade, quando o usuário alterna entre campos de entrada, etc.
Esse modelo foi feito para prevenir que dados sejam perdidos quando um usuário está navegando entre atividades e permite que o sistema faça a retirada segura de uma atividade da memória (pois recursos de sistema estão sendo requeridos em outro local) em qualquer momento quando ele estiver em modo onPause(). Note que isso implica que o usuário, ao pressionado o botão voltar na sua atividade não significa que ele esteja cancelando a atividade - isso apenas significa que ele está deixando a atividade e que seu estado corrente foi salvo de qualquer maneira. Cancelando a edição em uma atividade deve ser provido com algum outro tipo de mecanismo como um reverter explícito ou mesmo uma opção de desfazer.

Processo do ciclo de vida

O sistema Android tenta manter os processos de aplicações em memória pelo tempo máximo possível mas eventualmente será necessário remover processos antigos quando a memória começa a ficar menos disponível. A decisão de qual processo ser removido é intimamente ligado ao estado da interação do processo com o usuário. Em geral, existem quatro tipos de processos que podem ser baseados nas atividades que estão rodando, abaixo listadas em ordem de importância. O sistema vai matar processos menos importantes antes de matar processos mais importantes na tentativa de liberar memória.

  1. Atividade de frente (foreground activity) - A atividade que está sendo rodada naquele instante é considerada a mais importante. Seus processos somente serão mortos como último recurso, se ele usar mais memória que o que vem disponível no dispositivo. Geralmente nesse momento o dispositivo já chegou ao estado de uso de paginação, então é requerido matar esse processo será necessário para manter a resposta de interface.
  2. Atividade visível (visible activity) - Uma atividade que está visível mas o usuário não o têm na frente, como uma atividade que fica atrás de um diálogo em janela flutuante, por exemplo, é considerada extremamente importante e não será morta a não ser que seja requerido para que a atividade de frente possa continuar rodando.
  3. Atividade de fundo (background activity) - Uma atividade que não é visível ao usuário e que está em modo onPause() não é mais crítica e o sistema poderá, de maneira bastante segura, matar seu processo na memória para que possa ser usada por outros processos. Se esse processo precisar ser morto, quando o usuário navegar de volta a ele (fazendo com que ele se torne visível novamente na tela), o método onCreate(Bundle) dele será chamado com o savedInstanceState suprido pelo onSaveInstanceState(Bundle) para que possa ser reiniciado no mesmo estado que foi deixado.
  4. Processo vazio é um processo que não tem nenhuma atividade ou outros componentes de aplicação rodando nele (como um Service ou BroadcastReceiver). Eles são rapidamente mortos pelo sistema assim que é necessário mais memória. Então, quaisquer operações de fundo que precisam ser executadas fora da atividade devem ser executadas no contexto de uma atividade BroadcastReceiver ou Service para assegurar que o sistema saiba que é necessário mantê-la no ar para que seu processo seja executado.
Algumas vezes uma atividade necessita que uma operação que é longa seja executada independentemente do ciclo de vida da aplicação. Um exemplo é o de uma aplicação de câmera que esteja fazendo o upload de uma imagem para um site. O upload pode tomar bastante tempo e a aplicação deverá permitir ao usuário que ele saia dela sem que, no entanto, o upload pare. Para conseguir isso, sua atividade deverá iniciar um Service no qual o upload é feito. Isso permite ao sistema priorizar apropriadamente seu processo pela duração do upload, independentemente se a aplicação original está pausada, parada ou finalizada.

*traduzido livremente do site do Android

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.
Related Posts Plugin for WordPress, Blogger...