Android/Patró observador amb exemples
Patró observador amb Exemples
Que es el patró observador?
modifica
Tota aplicació amb interfície gràfica conté una sèrie d'elements per interactuar entre la persona i el Sistema . Per exemple, quan
es fa click a un botó o s'escriu en un Edit Text el programa s'ha d'assabentar d'aquest fet..
Un mecanisme com es el Patró observador ens ajuda a resoldre aquesta qüestió.
És un patró de comportament, ja que determina com s’ha de realitzar l'intercanvi de missatges entre els diferents objectes per aconseguir realitzar una tasca . O també poden ser diferents elements i tot això es representa en termes diagrames UML's.
Aquest patró es sol veure en els frameworks d’interfícies gràfiques orientades a
objectes, en què la forma de capturar els esdeveniments és subscriure “listeners” als
objectes que poden generar esdeveniments com botons radio butons o fins i tot el teclat.
Model conceptual del patró observador
• Subjecte ( Subject): Coneix als seus observadors. j j ) Proporciona una interfície per agregar, eliminar, notificar, .. Observadors.
• Observador (Observer): Defineix el mètode que usa el subjecte per notificar canvis en el seu estat
(update/notify).
• Subjecte Concret (ConcreteSubject): Manté l'estat d'interès per als observadors concrets i els notifica
quan canvia el seu estat. No tenen perquè ser elements de la mateixa jerarquia.
• Observador Concret (ConcreteObserver): Manté una referència al subjecte concret i implementa la interfície d'actualització, és a dir, guarden la referència de l'objecte que observen, així en cas de ser notificats d'algun canvi, poden preguntar sobre aquest canvi.
principi de Hollywood
modificaNo ens truquis; ja et truquem nosaltres
En la imatge de dalt ens mostra amb humor com funciona el principi de Hollywood. Això vol dir que ens hem d'esperar que hi hagi algú per nosaltres, i ells ja ens avisarà quan tingui alguna cosa per nosaltres quan ell dirà això va per vosaltres,
DIAGRAMA DE SEQÜÈNCIA
modificaQuan passa l'event determinat aquest envia un missatge a l'activity perquè ella fagi les diferents respostes.
Aquí veiem el diagrama de seqüència del principi de Hollywood qui crida com es crida
Pseudocodi exemple de primera òpcio del principi de Holywood
modificaclass Activity {
Button boto;
....
boto.avisam(this);
void clic() {.....}
}
class Button{
Activity a;
void avisam(Activity a) {this.a=a;}
void clic() {a.clic();}
}
Una llista de observadors
modificaAquí nomes veiem que hi ha un observable que rep la informació en un llista.
Exemples :
modificaJava per processos
modificaAra passarem a veure un exemple molt smple amb Java sense fer servir listeners, per processos . Podem dir que això que es un procces es lo mateix que uin listener.
package obs;
import java.util.Observable; //Observable és aquí
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class EventSource extends Observable implements Runnable
{
public void run()
{
try
{
//Fem un Reader per agafar el text que s'escriu dintre de la pantalla
final InputStreamReader isr = new InputStreamReader( System.in );
final BufferedReader br = new BufferedReader( isr );
while( true )
{
final String response = br.readLine();
setChanged();
notifyObservers( response );
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
Aquí veiem una classe java que espera que escrivim una línia per passar-la a tothom qui l'estigui observant.
/* Nom del fitxer: ResponseHandler.java */
package obs;
import java.util.Observable;
import java.util.Observer; /* this is Event Handler */
public class ResponseHandler implements Observer
{
private String resp;
public void update (Observable obj, Object arg)
{
if (arg instanceof String)
{
resp = (String) arg;
System.out.println("\nResposta rebuda: "+ resp );
}
}
}
Aquí veiem que quan li arriba on objecte arg que és un string es treu un missatge per pantalla.
/* Nom del fitxer: myapp.java */
/* És el programa principal */
package obs;
public class MyApp
{
public static void main(String args[])
{
System.out.println("Entra text >");
// crea un codi d'esdeveniment - llegeix des de stdin
final EventSource evSrc = new EventSource();
// crea un observer
final ResponseHandler respHandler = new ResponseHandler();
// subscriu l'observer al codi d'esdeveniment
evSrc.addObserver( respHandler );
// comença el thread d'esdeveniment
Thread thread = new Thread(evSrc);
thread.start();
}
}
Java amb un botó i una label
modificaBotó que espera
El botó té un listeners perquè quan es clica posa a la Label Botó clicat.
package listeners;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
/**
*
* @author Jaume
*/
public class Listeners {
private static JFrame pp;
private static JButton bb;
private static JLabel ll;
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
ll= new JLabel();
ll.setSize(20, 10);
pp =new JFrame ();
bb = new JButton();
bb.setText("clicam");
bb.setSize(100 , 100 );
pp.add(bb);
pp.add(ll);
bb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ll.setText(" botó clicat" );
}
});
pp.setSize(300, 300);
pp.setVisible(true);
}
}
Andriod + java
modificaCodi per fer la interfície
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MkM"
android:weightSum="1"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/com"
android:id="@+id/txtinixial"
android:layout_weight="0.05" />
<EditText
android:layout_width="178dp"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:layout_weight="0.07" />
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.05"
android:id="@+id/radiogrup"
android:baselineAligned="true">
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/km"
android:id="@+id/rdbKM"
android:layout_weight="1"
android:checked="false" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/Milles"
android:id="@+id/Milles"
android:layout_weight="1" />
</RadioGroup>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sss"
android:id="@+id/convertir"
android:layout_weight="0.09"
android:layout_gravity="center_horizontal|bottom"
/>
</LinearLayout>
Podem veure que aquí el listener del botó enlloc de definir-lo amb l'atribut onClick del button es fa en codi java.
Ara anem a agafar les funcions en el codi java:
package com.jaume.layouts;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
public class MkM extends Activity {
private EditText text;
private RadioButton milles;
private RadioButton km;
private Button but;
public static final double COL = 1.609344;
private void ini( ) {
text = (EditText) findViewById( R.id.editText );
milles =(RadioButton) findViewById(R.id.Milles);
km = (RadioButton) findViewById(R.id.rdbKM);
but= (Button) findViewById(R.id.convertir);
but.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
convertir(v);
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mk_m);
ini();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_mk_m, menu);
return true;
}
public void convertir (View v){
String con;
boolean mil;
boolean kme;
float oo;
con= text.getText().toString();
oo= Float.parseFloat(con);
mil= milles.isChecked();
kme=km.isChecked();
if (milles.isChecked()){
text.setText(String.valueOf(oo*COL));
milles.setChecked(false);
km.setChecked(true);
} else {
text.setText(String.valueOf(oo/COL));
milles.setChecked(true);
km.setChecked(false);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}