Reputation: 1835
In an Android app I'm developing, I'm not quite sure if the way I thought the model structure should be is the best in terms of ease of use and low complexity.
I need to represent the following relationship:
TypeA
(could be seen as a vault, just one throughout the program) holds all objects of TypeB
TypeB
(of which there can be 0..*) can hold objects of TypeC
TypeC
(related to TypeB
; 0..*) can hold objects of TypeD
TypeD
(related to TypeC
, 0..*)As there cannot be instances of either TypeC or TypeD without them being strongly related to a defined parent, I thought of the following structure (not including member variables such as title-String
s, program related boolean
s for view CheckBox
es, …:
TypeA
: Singleton
ArrayList<TypeB>
addTypeB(UUID)
, removeTypeB(UUID)
, getTypeBs
, getTypeB(UUID)
TypeB
: class
ArrayList<TypeC>
, UUID mId
addTypeC(UUID)
, removeTypeC(UUID)
, getTypeCs
, getTypeC(UUID)
TypeC
: class
ArrayList<TypeD>
, UUID mId
, UUID mParentTypeBId
addTypeD(UUID)
, removeTypeD(UUID)
, getTypeDs
, getTypeD(UUID)
TypeD
: class
UUID mId
, UUID mParentTypeBId
, UUID mParentTypeCId
I have already implemented the above structure using said four classes—one singleton, three "normal" classes—but am not too happy with the results at some points. For a particular instance of TypeD, I would have to type assignments like:
mTypeD= TypeA.getInstance(getActivity())
.getTypeB(typeBId)
.getTypeC(typeCId)
.getTypeD(typeDId);
Is there a better way to get the given relationship—or basically any relationship of that kind—into code? Probably the question isn't even Java-specific but instead relates to many object oriented programming languages.
EDIT: I have three ListViews for each type above TypeA, i.e., TypeB, TypeC, TypeD, containing all current instances and the possibility to open detail views for each single instance of either type. That’s why I thought about using the schema I provided in the first place.
EDIT2: On starting the app, users are presented with an empty ListView
if data has not yet been created. The ListView
that opens on application start represents a list of all instances of TypeB that can be found in TypeA’s ArrayList<TypeB>
. If the user taps on the “new” button on the ActionBar, a new instance of TypeB gets created and the user redirected that particular TypeB’s detail view. On leaving the detail view, s/he gets redirected back to the list of TypeB instances (at that point populated with only the one instance just created).
Upon tapping on one TypeB
instance in the list, the user gets directed to a(n empty) ListView
of TypeC
instances that belong to the TypeB
instance previously tapped on—without the connection to TypeB
, the TypeC
instances don’t make sense so it is crucial to somehow have all instances of TypeC
stored in a way that shows their relationship to a particular TypeB
instance.
For TypeC
->TypeD
it is the same. Upon creating a TypeC
instance in TypeC
instances ListView
, the TypeC
detail view of the newly created TypeC
instance is being opened, on pressing back the user gets redirected to the ListView
of TypeC
instances. On tapping on the TypeC instance, s/he gets to the (yet empty) ListView
of TypeD
instances—TypeD
instances are also strongly related to a particular TypeC
instance; without knowing the parent, they do not make sense.
For presenting the ListViews
I let an ArrayAdapter
go through all ArrayList
items of the given type. For deleting (by long-pressing an item --> ContextualActionBar
) or editing (same interaction as for previous action) I call the .remove
method of the parent's ArraylList
or open the detail view respectively.
Upvotes: 0
Views: 297
Reputation: 93668
You can always denormalize data like this- you don't need to just store it in 1 place, you can store it in multiple places. For example, you can have a hashmap of UUID to TypeD objects that allows you to directly look up any typeD by UUID. The catch is that you need to make sure to always update all the places you store it- if you want to remove a type d and you have it in this tree structure and in a hashmap you need to remove it from both or your two views of the data will be out of sync.
Upvotes: 1