Neste post abordamos a continuidade da aula anterior (parte 1) sobre o conceito do Polimorfismo aplicado na prática. Desta vez mostramos como criar as próprias classes para utilizar o conceito.
Neste post abordaremos o conceito de programação orientada a objetos conhecido como Polimorfismo. Como aplicar o conceito na prática usando a linguagem Java. Para entendermos estou organizando alguns vídeos para ilustrar melhor duas formas de utilização:
Usando as classes da linguagem Java de algumas bibliotecas que já estão disponíveis;
Construir nossos próprios tipos e então entender como tirar proveito do Polimorfismo.
Neste pequeno artigo veremos o primeiro caso.
Polimorfismo precisa ter uma hierarquia de classes com herança. Fonte imagem
De acordo com a Wikipédia (fonte), podemos considerar o conceito de Polimorfismo:
"Na programaçãoorientada a objetos, o polimorfismo permite que referências de tipos de classes mais abstratas representem o comportamento das classes concretas que referenciam. Assim, é possível tratar vários tipos de maneira homogênea (através da interface do tipo mais abstrato). O termo polimorfismo é originário do grego e significa "muitas formas" (poli = muitas, morphos = formas).
O polimorfismo é caracterizado quando duas ou mais classes distintas tem métodos de mesmo nome, de forma que uma função possa utilizar um objeto de qualquer uma das classes polimórficas, sem necessidade de tratar de forma diferenciada conforme a classe do objeto.[1]"
Vejamos o exemplo que fiz no vídeo:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Polimorfismo_parte1 {
/**
* POLIMORFISMO (aula pr‡tica - parte 1)
*
* Objetivos:
*
* 1) Entender o conceito de Polimorfismo na pr‡tica
* usando as classes j‡ existentes no Java
*
* @author Douglas Frari
* @see http://profdouglas.blogspot.com
*/
public static void main(String[] args) {
ArrayList lista1 = new ArrayList();
List lista2 = new ArrayList();
List lista3 = new LinkedList();
lista1.add("Elemento 1");
lista1.add("Elemento 2");
lista1.add("Elemento 3");
lista2.add("Elemento 1.1");
lista2.add("Elemento 2.1");
lista2.add("Elemento 3.1");
lista3.add("Elemento 1.1.1");
lista3.add("Elemento 2.1.1");
lista3.add("Elemento 3.1.1");
// imprimir elementos
imprimirLista(lista1);
imprimirLista(lista2);
imprimirLista(lista3);
}
static void imprimirLista(final List lista) {
for (String itemLista : lista) {
System.out.println(itemLista);
}
}
}
Conclusões
O conceito de polimorfismo em programação orientada a objetos é bastante útil para compreender como os objetos podem assumir diferentes responsabilidades no programa, dependendo de como foram declarados e como são instanciados pode-se reusar estruturas e operações. O resultado disso pode não ser tão útil assim, mas é. Quando se entende o conceito começamos a pensar de forma a favorecer o reuso e assim minimizamos a quantidade de linhas de código programáveis.
Usuários de
aplicativos em geral podem requerer mudar a orientação do aparelho
para visualizar melhor os conteúdos sendo exibidos na tela.
Dependendo do que está sendo visto é comum girar a orientação da
tela para o sentido horizontal (landscape) ou sentido vertical
(portrait).
(1) Tela em modo Portrait
Em aplicações Android
e iOS (smartphones e tablets) é comum implementar telas que vão
funcionar em diferentes perspectivas de orientação de tela. No
entanto, programadores de Android precisam estar atentos que quando
ocorrem mudanças de orientação no aplicativo, o comportamento
padrão do Android recria a Activity em execução, chamando os
métodos do ciclo de vida: onPause(), onStop(), onDestroy(), para em
seguida chamar o método onCreate() novamente, além dos métodos do
ciclo de vida: onStart() e onResume().
Problema / Solução
Se a tela atual da
sua aplicação apenas desenha elementos visuais sem obter dados de
fontes custosas (para memória em geral ou uso da Internet para
baixar os dados), então esse procedimento padrão do Android não
será um problema. Contudo, caso sua Activity requeira dados da
internet ou algum outro tipo de esquema de processamento “mais
pesado” para ser realizado, talvez seja necessário evitar
recarregar a instância da Activity, mantendo o estado dos objetos
carregados na memória. Desta forma podemos evitar consultar a rede
novamente, além de otimizar o uso do processamento do aparelho,
melhorando o consumo da bateria. :)
Esse comportamento pode
ser realizado de 2 formas: (que eu conheço)
Salvar os dados
atuais (o estado atual) utilizando o mecanismo do ciclo de vida da
Activity do Android, através dos métodos
onSaveInstanceState(bundle) para salvar, e o
onRetainNonConfigurationInstance() para recuperar os dados do estado
atual;
Alterar o
comportamento default do Android, descrito acima, evitando que a
Activity seja automaticamente recriada. Desta forma o Android apenas
irá notificar Activity que ocorreu uma mudança de orientação,
através do método onConfigurationChanged(Configuration c).
Neste post vou mostrar
como podemos implementar abordagem (2), ou seja, como evitar que o
Android recrie Activity do ciclo de vida do aplicativo.
Passo 1: altere o
arquivo AndroidManifest.xml conforme o exemplo abaixo adicionando a
propriedade chamada (android:configChanges="orientation|screenSize")
da sua Activity:
Passo 2: implementar no
código Java da sua Activity o método conforme exemplo:
package br.com.blogspot.profdouglas.dicas3.orientationchange;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
public class OrientationChange extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_orientation_change);
Log.d("DOUGLAS", "OrientationChange.onCreate");
TextView orientationTextView = (TextView) findViewById(R.id.orientationTextView);
// detect the current orientation
int currentOrientation = getResources().getConfiguration().orientation;
if (currentOrientation == Configuration.ORIENTATION_LANDSCAPE) {
// setting orientation landscape
orientationTextView.setText(R.string.orientation_landscape);
} else if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
// setting orientation portrait
orientationTextView.setText(R.string.orientation_portrait);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_orientation_change, menu);
return true;
}
@Override
protected void onStart() {
super.onStart();
Log.i("DOUGLAS", "OrientationChange.onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.i("DOUGLAS", "OrientationChange.onResume");
}
@Override
protected void onStop() {
super.onStop();
Log.i("DOUGLAS", "OrientationChange.onStop");
}
@Override
protected void onPause() {
super.onPause();
Log.i("DOUGLAS", "OrientationChange.onPause");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i("DOUGLAS", "OrientationChange.onDestroy");
}
/**
* Caution: Beginning with Android 3.2 (API level 13), the "screen size"
* also changes when the device switches between portrait and landscape
* orientation. Thus, if you want to prevent runtime restarts due to
* orientation change when developing for API level 13 or higher (as
* declared by the minSdkVersion and targetSdkVersion attributes), you must
* include the "screenSize" value in addition to the "orientation" value.
* That is, you must decalare
* android:configChanges="orientation|screenSize". However, if your
* application targets API level 12 or lower, then your activity always
* handles this configuration change itself (this configuration change does
* not restart your activity, even when running on an Android 3.2 or higher
* device).
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d("DOUGLAS", "MainActivity.onConfigurationChanged");
TextView orientationTextView = (TextView) findViewById(R.id.orientationTextView);
if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
Log.i("DOUGLAS",
"MainActivity.onConfigurationChanged (ORIENTATION_PORTRAIT)");
// setting orientation portrait
orientationTextView.setText(R.string.orientation_portrait);
} else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Log.i("DOUGLAS",
"MainActivity.onConfigurationChanged (ORIENTATION_LANDSCAPE)");
orientationTextView.setText(R.string.orientation_landscape);
}
}
}
Observe o javadoc que
deixei para que você entenda porque a propriedade do manifest
precisou utilizar dois valores. A figura (2) demonstra o log (da view LogCat) demonstrando que a Activity não foi recriada, mas o método onConfigurationChanged foi notificado.
(2) Tela em modo Landscape sem recriar a Activity após mudar orientação
Conclusão
Ao executar seu
aplicativo agora, quando ocorrer mudanças de orientação de tela sua Activity não será recriada e o método onConfigurationChanged
será automaticamente notificada a cada mudança de orientação.
Como sugestão, caso queira fazer algo específico para cada modo de
orientação, pode-se usar a lógica da condição implementada no método, que atualmente possui instruções com
logs. Dependendo do cenário no qual seu aplicativo está sendo
usado, essa dica pode ser útil para você.
Assim que possível vou
fazer uma vídeo aula sobre isso também e colocar aqui. O código
fonte do exemplo do projeto pode ser baixado aqui.