quinta-feira, 14 de junho de 2018

Rumo ao Certificado Android: Recycler View

O que é?
Basicamente é uma combinação de uma List View com Scroll View, mas otimizado para economizar memória e facilitar o gerenciamento dos itens.

1. Adicionar a dependência do RecyclerView no Gradle
No arquivo Gradle, colocar o seguinte, por exemplo (o número da versão pode ser alterada):

dependecies{
    compile 'com.android.support:recyclerview-v7:24.1.1'
}

2. Criando um RecyclerView Layout
No arquivo XML do layout que vai receber o RecyclerView, adicionar o dito cujo. por exemplo (estou omitindo as configurações do FrameLayout):

<FrameLayout>
   <android.support.v7.widget.RecyclerView
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/rv_nome">

   </android.support.v7.widget.RecyclerView>
</FrameLayout>

3. Criar um Layout para os Itens
Em seguida, precisamos criar um arquivo Layout com a disposição dos elementos que compõem os itens do RecyclerView. Cada item vai gerar um elemento definido neste arquivo (lembrando, super simplificando para fins didático aqui).

<FrameLayout>
    <TextView
      android:id="@+id/tv_textView1" />
</FrameLayout>


4. Criar o View Holder
ViewHolder é a representação lógica dos itens, portanto, geralmente ele possui os mesmos elementos que compõe o layout de itens. Uma classe ViewHolder herda do ViewHolder (jura?):

public class NomeHolder extends RecyclerView.ViewHolder{

    TextView textView1;

    public NomeHolder(View itemView){
        super(itemView);
              
       textView1 = (TextView) itemView.findViewById(R.id.tv_textView1);

    }
        
    public void bind(String value){
       textView1.setText(value);
    }
}

O construtor recebe como parâmetro o layout do item, e dentro do construtor, pegamos a referência do campo para o objeto TextView da classe. Isso pode ser feito para outros campos. Também acho interessante criar um método "bind" para setar os valores dos campos que vão aparecer, embora isso fica a gosto do programador.

Obs: Muita gente geralmente cria a classe ViewHolder como uma classe interna do Adapter, que vamos ver em seguida. Isso pode trazer bastante facilidade, dado que os Adapters são específicos para o ViewHolder

5. Criar o Adpter
Adapter é a classe que gerencia os dados. É nele que colocamos os dados e ele que liga os mesmos nos itens do layout. A classe de um Adapter fica assim (campo R.layout.ItemLayout é o layout que criamos no passo 3):

public class NomeAdapter extends RecyclerView.Adaper<NomeHolder>{
    
  List<String> data;

  public NomeAdapter(List<String> loadedData){
    data = loadedData;
  }

  @Override
  public NomeHolder onCreateViewHolder(ViewGroup vg, int viewType){
    //Aqui nós criamos o Holder
    Context context = vg.getContext();
    LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.ItemLayout, 
                                 vg,
                                 false);
    return new NomeHolder(view);
  }

  @Override
  public void onBindViewHolder(NomeHolder holder, int position){
     holder.bind(data[position]);
  }

  @Override
  public int getItemCount(){
    return data.length();
  }
}

Começando com o override do método onCreateViewHolder, que é especificamos como instanciamos o ViewHolder para este RecyclerView.
Já em onBindViewHolder, é especificado o que vai ser preenchido o item, no caso, recebe dois parametros, o holder que vai ser usado e a posição do item que está. Para facilitar, você pode usar uma lista, um array, ou qualquer estrutura de dados semelhante para isso.
Por último, temos o método getItemCount, que deve retornar quantos itens deve estar na lista.

6. Determinar o LayoutManager
Isso é importante porque dependendo do LayoutManager, a forma como os itens vão ser mostrados se modifica. Existem três LayoutManager por padrão no Android:

  • LinearLayoutManager: exibe os itens linearmente;
  • GridLayoutManager: exibe os itens em uma grade com espaços uniformes;
  • StaggeredGridLayoutManager: exibe os itens em uma grade, mas o tamanho sempre se adaptará ao conteúdo.

7. Instanciar  e configurar o Adapter na Activity
Auto-explicatória. Se queremos ver ele rodando, precisamos rodar ele numa Activity.

RecyclerView recycler;
NomeAdapter adapter;
protect void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

    setContentView(R.layout.layoutActivity);
    recycler = (RecyclerView) findViewById(R.id.rv_nome); //Passo 2
    

   //Configurar o layout
   LinearLayoutManager layoutManager = new LinearManager(this);
   recycler.setLayoutManager(layoutManager);
   
   List<String> data = loadData();

   adapter = new NomeAdapter(data);
   recycler.setAdapter(adapter);

}

8. Criar os Listener dos eventos que deseja
Por exemplo, se tiver um elemento interativo que queira que algo aconteça quando clica em cima, é agora que deve ser feito:

8.1 Alterar o adapter para criar uma Interface e adicionar um campo para referência de um mesmo

public class NomeAdapter extends RecyclerView.Adaper<NomeHolder>{
   final private ListItemClickListener listener;

   public interface ListItemClickListener{
     void onListItemClick(int clickedIndex);
   }
}

8.2 Modificar o construtor para setar o listener

public class NomeAdapter extends RecyclerView.Adaper<NomeHolder>{
   final private ListItemClickListener listener;

   public interface ListItemClickListener{
     void onListItemClick(int clickedIndex);
   }

   public NomeAdapter(List<String> loadedData, ListItemClickListener itemListener){
    data = loadedData;
    listener = itemListener;
  }
}

8.3 Implementar a interface OnClickListener no ViewHolder

public class NomeHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
   @Override
   public void onClick(View view){
      int clickedPosition = getAdapterPosition();
      listener.onListItemClick(clickedPosition);
   }
}

8.4 Setar o Listener no construtor da ViewHolder

public class NomeHolder extends RecyclerView.ViewHolder implements View.OnClickListener{

  public NomeHolder(View itemView){
        super(itemView);
              
       textView1 = (TextView) itemView.findViewById(R.id.tv_textView1);
       itemView.setOnClickListener(this);
    }

}

8.5 Implementar a interface criada no passo 1 na Activity e alterar a instanciação

public class Activity extends Activity implements NomeAdapter.ListItemClickListener{

   @Override 
   public void ListItemClickListener(int clickedIndex){

   }
   
   [...]
   adapter = new NomeAdapter(data,this);
   [...]
}

Bem, isso é tudo, lembrando que o que registrei aqui é apenas uma maneira de lidar com RecycleView, mas de forma macro, são estes passos que você deve tomar.

terça-feira, 12 de junho de 2018

Rumo ao Certificado Android: Async Task - Criando novas threads

Como dito anteriormente, uma requisição WEB não pode ser feita na thread principal do aplicativo. Isso ocorre porque o app precisaria ficar em um estado suspenso enquanto a requisição não fosse concluída, fazendo com que o programa não respondesse. Para evitar isso, precisamos criar uma thread secundária, que irá fazer o manejamento da requisição, enquanto que a thread principal continuará com a interação do usuário.

Para isso, podemos criar uma AsyncTask. Para isso, podemos criar uma classe que vá herdar a classe AsyncTask com três parâmetros: Params, Progress, Result. Abaixo temos um exemplo de código:

public class ActivityAsyncTask extends AsyncTask <URL, void, String>{

}

No código acima, estamos criando uma AsyncTask cujo parâmetros são:

  • Um objeto URL como parâmetros gerais;
  • Nada para gerenciamento de progresso;
  • Uma String como resultado;
O próximo passo será definir o método "doInBackground", como mostra abaixo:


public class ActivityAsyncTask extends AsyncTask <URL, void, String>{

    @Override
    protected String doInBackground(URL... urls){

    }

}

Note que o parâmetro do método doInBackground vai depender do que for passado na hora da definição da herança, neste caso, se definiu que na parte de parâmetros gerais, você deve passar URL, o parâmetro do método vai pedir para passar um array de URLs. Também observe que o retorno bate com o terceiro elemento definido, ou seja, uma String.
Mas o mais importante, o que faz este método? Este é o método principal para a nova thread. É aquela que vai ser executada em outra thread, logo, se quisermos fazer uma requisição HTTP, seria aqui que nós executaria essa requisição.

Uma vez que o processo seja concluído, o método onPostExecute será executado, recebendo o que for retornado no método doInBackground. É aqui que você definirá o que deve ser feito com o resultado:

public class ActivityAsyncTask extends AsyncTask <URL, void, String>{

    @Override
    protected void onPostExecute(String result){

    }

}

Claro que o algoritmo não vai executar sem ser chamado. Para isso, onde você desejar iniciar o processo, você instanciará um objeto da classe AsyncTask que você criou e executará o comando execute. Exemplo:

public void randomMethod(URL url){
  new ActivityAsyncTask().execute(url);
}

Por hoje é tudo.

Rumo ao Certificado Android: JSON

Para lidar com arquivos JSON no Android é simples:

1. Inicialize um objeto JSONObject com uma string contendo o JSON:

JSONObject json = new JSONObject(stringJSON);

2. Para pegar um objeto, utilize o seguinte método a partir do objeto inicializado:

JSONObject object = json.getJSONObject("nomeDoObjeto");

3.Para pegar um valor do objeto, use os métodos getString:

String valor1 = object.getString("campo1");
String valor2 = object.getString("campo2");

E essa foi a dica de hoje!

sexta-feira, 8 de junho de 2018

Rumo ao Certificado Android: Requisição HTTP

Hoje vamos aprender a fazer uma requisição HTTP. Existe várias formas de fazer, mas selecionei uma. Veja o código a seguir:


O que o código faz? Com um objeto URL, nós abrimos uma conexão e pegamos uma Stream de entrada, que é por onde o dado vai chegar. Usaremos o objeto Scanner para ler essa entrada. Um truque para este caso é usar o delimitador "\A", que significa "Início da Entrada". Isso permite o Scanner criar tokens e poder criar buffer de forma dinâmica, uma vez que o protocolo HTTP não obriga enviar o tamanho do pacote de dados. 

Agora estamos quase aptos a fazer uma requisição HTTP, mas antes, existem duas condições para nós podermos executar o código acima:

1. Precisamos de uma permissão de acesso a Internet. Para isso, abra o arquivo manifesto (manifests/AndroidManifest.xml)

2. A requisição HTTP não pode ser executada em uma thread de atividade principal. E esse será o nosso assunto a seguir.

quinta-feira, 7 de junho de 2018

Rumo ao Certificado Android: Criando URL de forma segura

Olá, hoje vai uma dica rápida que vai ser uma das bases do tutorial de como obter dados da Internet. Hoje vamos falar de como montar uma URL:

O ideal é termos as partes da URL parametrizadas, geralmente tendo o endereço do site como uma constante, assim como o nome dos parâmetros. Como no exemplo abaixo:



Com isso, podemos usar o URI Builder para gerar nossa URI:


Essa forma de montar permite não nos preocupar com acentos, caracteres especiais, entre outras peculiaridades. Agora para converter para URL é só fazer o seguinte:

Como nós usamos o URI Builder, dificilmente a exceção será executada.

quarta-feira, 6 de junho de 2018

Rumo ao Certificado Android: Menus


Hoje vou mostrar um guia rápido de como criar um toolbar com menu:


1. Com o botão direito do mouse, clique na pasta "Res" e no menu vá em New > Android Resource File

2. Na tela seguinte, digite o nome do Resource em "File Name" e escolha a opção "Menu" em "Resource Type". Então, clique em ok.

3. Vamos adicionar um item. Abra o arquivo que acabamos de criar e coloque para ver o código. Insira o seguinte código:



Explicando os atributos do item:
  • android:title > é o nome que vai aparecer no menu/botão. Aqui no caso, estamos usando uma resource de string, principalmente porque é uma recomendação da Google que qualquer string que seja inserido, esteja em um resource e não no código;
  • android:orderInCategory > o número indica a posição na barra de menu. O número 1 significa que o elemento será o primeiro item;
  • android:id > id do item para refêrencia;
  • app:showAsAction > Aqui estamos dizendo que este item deve aparecer somente se houver espaço na tela para ele ser renderizado.
4. Agora no código da nossa Activity que receberá o menu, colocamos o seguinte código:
Esse código é para nós inflar o menu. Note que ele tem um método para isso que deve ser sobrescrito.

5. Por fim, vamos querer realizar uma ação para quando esse item for selecionado. Neste exemplo, vou criar mostrar um toast. Note que assim como o método anterior, este também será sobrescrito.


Então por hoje é isso!

terça-feira, 5 de junho de 2018

Rumo ao Certificado Android: Atividades e Layouts

Uma atividade é um dos quatros software base de um aplicativo Android e o mais fundamental, por este ser aquele que o usuário vai interagir diretamente. Toda atividade possui uma interface pelo qual o usuário vai manipular o aplicativo.

Essa interface geralmente é definido por um arquivo de layout, que se encontra dentro da pasta "res" do projeto.

Geralmente um arquivo de layout é atribuído a uma atividade através do comando setContentView, como mostra o exemplo abaixo:



Já o arquivo de layout é um arquivo XML, como visto abaixo:


Os elementos deste XML pode ser classificado em dois tipos:
  • Layouts: define o tipo de layout que os elementos vão seguir;
  • Componentes:define um componente que será exibido;
Um Layout sempre será a raíz do arquivo XML e outros layouts podem estar aninhados dentro para combinar efeitos. Entretanto, é sempre recomendado evitar muitos elementos um dentro do outro por questão de desempenho.
Os principais layouts são:
  • Linear Layout: os elementos são colocados um ao lado do outro (caso a orientação do layout seja horizontal) ou um abaixo do outro (orientação do layout seja vertical);
  • Relative Layout: as views são posicionados em relação a outros views;
  • Frame Layout: View feitas para conter um elemento. Geralmente usado para exibir dados que ainda vão ser carregados;
  • Scroll Layout: Um frame layout feita para rolar quando a tela é menor e não é possível mostrar tudo;
  • Constraint Layout: o mais novo layout que permite posicionar elementos através de restrições;
Um componente sempre possui uma funcionalidade na tela, pode ser uma caixa de texto, uma imagem, um campo para ser preenchido. Os mais comuns são:
  • TextView: Exibe um texto na tela e geralmente não tem interação;
  • EditText: Cria um campo de texto;
  • ImageView: Cria uma imagem na tela;
  • Button: Cria um botão na tela;
  • Chronometer: mostra um cronometro na tela;
Vários outros componentes existem, podemos ver em um outro texto;