07
Na tomto místě zmíníme jedno téma, které v podstatě s aplikacemi pro Android nesouvisí. Pro pokračování v příkladu z minulé kapitoly totiž potřebujeme předat informace o případných změnách záznamů či jejich přidání nebo odebrání komponentě ListView
. Pro tyto situace se dobře hodí návrhový vzor Pozorovatel/Posluchač (Observer/Listener). Nebudeme zde problematiku návrhových vzorů rozebírat podrobně, ale zmíníme alespoň základní fakta. Omlouváme se pokročilejším čtenářům za zjednodušení, kterých se tím v některých aspektech dopustíme. Věříme, že pro naši cílovou skupinu čtenářů jsou tato zjednodušení vhodná.
Programátoři s delší praxí brzy zjistí, že některé situace se v projektech opakují. V našem případě je to situace, kdy jedna třída potřebuje být informována o změnách jiné třídy. Ať už se jedná o okno, které má reagovat na stisk tlačítka, o tabulku, která se má překreslit v důsledku načtení nových dat, nebo o ListView
, kde potřebujeme aktualizovat data po úpravě některého záznamu.
Pro podobné situace a společné šablony řešení těchto situací se používá označení návrhové vzory (design patterns). Existuje tedy například návrhový vzor Pozorovatel/Posluchač (Observer/Listener), který popisuje obecné řešení situace, kdy jedna třída potřebuje být informována, kdykoli nastane zvolená událost v jiné třídě. Existují ale také další návrhové vzory pro jiné, často opakované situace.
Protože se návrhové vzory vyskytují často, nabízí moderní programovací jazyky v rámci svých knihoven standardizované implementace těchto návrhových vzorů. Pro návrhový vzor Pozorovatel nabízí Java třídu Observable
a rozhraní Observer
, které nám zjednoduší použití návrhového vzoru
Observable
Třída Observable
implementuje chování objektu, ve kterém se dějí změny a který chce o těchto změnách informovat pozorovatele, kteří o to požádají. Nabízí metody:
addObserver(Observer o)
setChanged()
notifyObservers()
Třída nabízí i další metody, ale ty nebudeme v našem projektu potřebovat.
Observer
Rozhraní Observer implementují ty třídy, které chtějí být informovány o změnách. Implementace rozhraní vyžaduje přítomnost jediné metody:
update(Observable zdroj, Object o)
Observable
v okamžiku, kdy bude chtít pozorovatele informovat o nastalé změně.Využijeme návrhového vzoru Pozorovatel k předávání informací o změnách v záznamech. Třída Zaznam
bude Observable
a bude sdělovat informace o změně svého stavu třídě Data
. Třída data bude také Observable
a předá informace o přidání, změně či rušení položek v seznamu záznamů hlavní aktivitě a tedy i komponentě ListView
.
Zaznam
a Data
nastavíme jako potoky třídy Observable
:public class Zaznam extends Observable { … public class Data extends Observable implements Observer{ …
Data
implementujeme rozhraní Observer
a přidáme metodu update()
:public class Data extends Observable implements Observer{ … @Override public void update(Observable observable, Object o) { this.setChanged(); this.notifyObservers(); }
public class MainActivity extends AppCompatActivity implements Observer { ... @Override public void update(Observable observable, Object o) { this.aktualizuj(); }
setChanged()
a notifyObservers()
. Při každém přidávání záznamu ve třídě Data
navíc musíme přidat novému záznamu jako pozorovatele aktuální instanci třídy Data
:public class Zaznam extends Observable { … public void invertujDulezite() { this.dulezite = ! this.dulezite; this.setChanged(); this.notifyObservers(); } public class Data extends Observable implements Observer{ ArrayList<Zaznam> data = new ArrayList<Zaznam>(); protected void nactiData() { ... z = new Zaznam("Terra Mystica", "Naučil jsem se novou deskovou hru.", false); z.addObserver(this); this.data.add(z); this.setChanged(); this.notifyObservers(); } ... @Override public void update(Observable observable, Object o) { this.setChanged(); this.notifyObservers(); }
Observable
metody:
addObserver(Observer o)
… přidá do seznamu pozorovatelů další třídu pozorovatel,setChanged()
… volá se v okamžiku, kdy se změní atributy třídy,notifyObservers()
… volá se v okamžiku, kdy chceme informovat pozorovatele.Observable
a jeho metodu update(Observable zdroj, Object zprava)
.Listener
) používá i knihovna Swing pro tvorbu grafického rozhraní aplikací a další knihovny Javy.