I'm trying to make my app with PM design (MVC + Presentation Model), but I've already stuck on how to cleverly wrap Model classes in Presentation Model classes. Now, I write a simple code where a picture and a text are changed based on values in an instance of Model class.
// Disclaimer:
// View and Controller are merged in this sample for clarity's sake.
Enum
Enum AnimalSpecies {
Dog, Cat, Rabbit, Bird,
}
M of MVC + RM
class Model extends Observable {
// in my actual code Model has 10+ member variables and most of them are Enum
protected AnimalSpecies species;
protected String name;
protected Object update;
public void setSpecies (AnimalSpecies species) {
this.species = species;
notifyUpdate(species);
}
public void setName (String s) {
this.name = s;
notifyUpdate(name);
}
public void notifyUpdate(Object o) {
this.update = o;
this.setChanged();
this.notifyObservers(update);
}
}
RM of MVC + RM
class PresentationModel extends Observable implements Observer {
@Override
public void update(Observable model, Object data) {
// Called when notified by Model
// No idea what to write... but what I want to do is,
// a) determine what text for View to display
// b) determine what pics for View to display,
// based on values of Model.
this.setChanged();
this.notifyObservers(update);
}
}
VC of MVC + RM
class View extends Activity implements Observer {
// This is View + Controller, so it'd implement some interfaces like onClickListener,
// and in events such as onClick(), values of Model class are changed,
// but for clarity's sake, I keep everything in onCreate() event.
TextView header;
TextView footer
ImageView imgview;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
header = (TextView) findViewById(R.id.header);
footer = (TextView) findViewById(R.id.footer);
imgview = (ImageView) findViewById(R.id.imgview);
Model model = new Model();
PresentationModel pm = new PresentationModel();
model.addObserver(pm);
pm.addObserver(this);
model.setSpecies(AnimalSpecies.Cat);
model.setName("Max");
}
@Override
public void update(Observable pm, Object data) {
// Called when notified by PresentationModel
// *** varies based on parameters from PresentationModel
header.setText(***);
footer.setText(***);
imgview.setImageResource(R.drawable.***);
}
}
My question: how to write a logic in public void update()
of class PresentationModel
? I can get only an Object
variable from NotifyObserver()
, and even with nested switch
or if
... else
, I can't come up with codes at all...
Hmm, you probably want to tell your listeners what changed. For example, if the name field changed in the model, call notifyObservers(update, PROPERTY_NAME)
. Then the presentation model just needs logic to handle name changes.
That said, I wouldn't recommend using Presentation Model without a framework. There's too much complexity and code required to fire events and move data around properly. Actually, even with a framework, there's a significant learning curve - but I do think it's a nice architecture for larger projects.
JGoodies Binding is a good example of a Presentation Model framework. However, it's targeted at Swing applications. It can be adapted for Android with some effort, but I would look to see if a good Android-specific framework exists.