Android

18 nov, 2016

Intents – Passagem de parâmetros entre telas

Publicidade

As Intents possibilitam que informações possam ser transmitidas de uma tela para outra, conforme o usuário navega pela aplicação. Esse é um item bem relevante no desenvolvimento mobile, pois muitas vezes precisamos de uma informação pequena, como a posição de uma lista em que o usuário selecionou algum item para ser utilizada na tela seguinte. E, muitas vezes, essa informação, por ser pequena, não vale a pena ser salva num banco de dados ou Shared Preferences, pois pode ser descartada na tela seguinte. Pensando nisso, o Android criou as Intents, que não servem somente para passagem de parâmetros, que é nosso objetivo aqui.

Vamos imaginar uma lista de produtos de papelaria, onde, ao selecionar um da lista, o usuário é direcionado para outra tela, que conterá detalhes do produto, como preço, quantidade de itens em estoque, descontos etc. Veja a imagem abaixo:

intents-tela-2

Intents

O Android define as Intens como “uma descrição abstrata de uma operação que pode ser realizada”. O nome é sugestivo: determinam uma intenção de determinada ação. Essas ações podem ser tanto dentro da própria aplicação, como chamar outra tela, quanto até mesmo compartilhar algo com uma aplicação que possa atender à solicitação. Este artigo tem o foco de mostrar o uso das Intents para passagem de parâmetros entre telas.

Iniciando outra tela

Como foi dito, a Intent é uma intenção, e uma das intenções possíveis é inicializar uma outra tela. Para isso, é preciso criar uma instância de Intent passando o contexto atual e a nova activity desejada.

Intent intent = new Intent(this, ItemDetalheActivity.class);

Com essa instância criada, será possível passar os parâmetros desejados, que podem ser de diversos tipos: int, String, float entre outros. A figura abaixo mostra alguns dos possíveis tipos de valores.

intents-3

Depois passamos os parâmetros desejados e iniciamos uma nova activity passando essa “intent” que foi criada.

        intent.putExtra("itemSelecionadoTitulo", titulo);
        intent.putExtra("itemSelecionadoPosition", position);

Mas, mesmo fazendo isso, ainda não está completo. Perceba que armazenamos dentro de uma Intent os valores que estamos passando, mas ainda uma outra activity não foi iniciada. Então, usamos o método startActivity(intent) para iniciar nossa nova tela.

        startActivity(intent);

Se a essa altura do campeonato você tentar rodar o projeto, verá que ocorrerá o seguinte erro, como mostrado na figura abaixo:

intents-4

Esse erro ocorre porque ainda falta mais um pequeno passo. Toda tela que uma aplicação utiliza deve ser declarada no Manifest File. Isso porque o Android detecta por esse arquivo quais são as telas existentes na aplicação. Se você perceber, toda vez que cria um projeto, o Android Studio se encarrega de deixar declarado para a primeira tela o seguinte código:

       <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

Vamos analisar cada parte. A primeira tag é uma activity; assim, ele sabe que estamos falando de uma Activity. A segunda tag, que está dentro da tag activity é intent-filter, que pode ser entendida como características que são anexadas à Intent, e servirão para o elemento que for tratar essa Intent. Difícil de entender!? Calma, vamos lá: o Android possui um jeito peculiar de raciocinar, que é muito útil em muitos aspectos, incluindo as Intents.

As intents são “jogadas” para o sistema operacional, e quem puder “responder” a elas poderá ser solicitado. Assim, você pode compartilhar (share) um conteúdo com contatos do WhatsApp, Hangouts, Gmail, enfim, várias aplicações podem tratar essa sua solicitação.

Portanto, os filtros servem como características que são adicionadas às Intents. No caso, quando uma activity é a primeira de uma aplicação, é preciso explicitar que ela é a principal. Você deve ter notado que o intent-filter não trabalha sozinho, e existem 3 tipos de informações que podem ser adicionadas a ele: <action>, <category>, <data>, além dos extras e flags (que são setados em tempo de execução via código).

A action é uma string que especifica uma ação genérica como exibir, selecionar ou enviar. A category é uma string que especifica como o componente que receber essa Intent deverá tratá-la. E data é uma string que está mais associada à action, ela especifica o tipo de dado; assim, se a action for ACTION_EDIT, então essa tag, data, deverá conter o dado a ser editado, no formato URI.

Pode haver em uma aplicação Intents customizadas, mas o mais comum de ocorrer é sua aplicação querer responder a uma Intent gerada pelo sistema, como escrever, ler, entre outras possíveis ações.

Para ter mais uma activity na aplicação, não é necessário declarar ação ou categoria para essa Intent, ou seja, ela não precisa de intent-filters nesse caso. Veja o código:

<activity android:name=".ItemDetalheActivity"/>

Passando objetos do tipo Parcelable

Imagine um objeto “Usuário” que possua diversos atributos, como nome, idade, endereço, e muitos outros. Fica um pouco complicado ficar passando atributo por atributo. O interessante é que tenhamos uma forma de passar um objeto inteiro. Existe uma forma de fazer isso no Android: Parcelable e Serializable. A diferença entre eles é mais uma questão de processamento. O Serializable, que vem do Java, é mais lento; já o Parcelable é uma implementação do Android e é mais performático. A primeira mudança no código é mexer no modelo; nesse caso, já possuo a classe modelo, e só será modificado o código para implementar um Parcelable.

package paulacr.net.intents;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by paularosa on 1/21/16.
 */
public class Item implements Parcelable {

    private Integer icon;
    private String title;
    private Integer color;
    private String tag;

    public Item(Integer icon, String title, String tag, Integer color){
        this.icon = icon;
        this.title = title;
        this.color = color;
        this.tag = tag;
    }

    protected Item(Parcel in) {
        title = in.readString();
        icon = in.readInt();
        color = in.readInt();
        tag = in.readString();
    }

    public static final Creator<Item> CREATOR = new Creator<Item>() {
        @Override
        public Item createFromParcel(Parcel in) {
            return new Item(in);
        }

        @Override
        public Item[] newArray(int size) {
            return new Item[size];
        }
    };

    public Integer getIcon() {
        return icon;
    }

    public void setIcon(Integer icon) {
        this.icon = icon;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Integer getColor() {
        return color;
    }

    public void setColor(Integer color) {
        this.color = color;
    }

    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(title);
        dest.writeInt(icon);
        dest.writeInt(color);
        dest.writeString(tag);
    }
}

Depois disso, devemos mudar a Intent que estamos enviando para a outra tela, de detalhe de item.

intent.putExtra("itemSelecionado", item);

Feito! Agora precisa-se tratar o lado que vai receber esses dados, pois até agora foi visto como enviar, mas não como receber. Na activity da tela seguinte, que está recebendo os valores, vamos capturar esses dados que foram enviados.

        Intent intent = getIntent();
        Item item =   intent.getParcelableExtra("itemSelecionado");

E então basta setar os valores desejados que vieram da tela anterior, veja abaixo:

       if(intent.hasExtra("itemSelecionado")) {
            imagem.setImageResource(item.getIcon());
            titulo.setText(item.getTitle());
        }

Conclusão

As Intents são muito úteis no desenvolvimento mobile e estão presentes em diversas aplicações consideradas sucesso em Android, além de facilitarem consideravelmente a troca de informações entre telas de forma rápida e fácil.

O exemplo usado neste artigo encontra-se no GitHub no seguinte link: https://github.com/paulacr/Intents.