1

I am working on a project that involves me having to share an array list of objects with all of the activities that make up the application. Until recently I was passing the list between activities by implementing the parcelable interface. An example of this is seen below:

MenuItem class:

ublic class MenuItem implements Parcelable {

private String name;
private double price;
private int qty;
private String info;

public MenuItem(String name, double price) {
    super();
    this.name = name;
    this.price = price;
}
public MenuItem() {
    // TODO Auto-generated constructor stub
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public double getPrice() {
    return price;
}
public void setPrice(double price) {
    this.price = price;
}

public int getQty() {
    return qty;
}
public void setQty(int qty) {
    this.qty = qty;
}
public String getInfo() {
    return info;
}
public void setInfo(String info) {
    this.info = info;
}
@Override
public String toString() {
    return name;
}


//Parcelable methods.
public static final Parcelable.Creator<MenuItem> CREATOR = new Parcelable.Creator<MenuItem>() {

    @Override
    public MenuItem createFromParcel(Parcel source) {
        return new MenuItem(source);
    }

    @Override
    public MenuItem[] newArray(int size) {
        return new MenuItem[size];
    }
};

public MenuItem(Parcel source) {
    this();
    readFromParcel(source);
}

private void readFromParcel(Parcel source) {
    name = source.readString();
    price = source.readDouble();
}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(name);
    dest.writeDouble(price);
}

}

Order class - which I would change to be the Singleton (holds list of menu items)

public class Order implements Parcelable {


private int covers;
private int table;
private ArrayList<MenuItem> items;


public Order(){
    super();
    this.items = new ArrayList<MenuItem>();

}

public static final Parcelable.Creator<Order> CREATOR = new Parcelable.Creator<Order>() {

    @Override
    public Order createFromParcel(Parcel source) {
        return new Order(source);
    }

    @Override
    public Order[] newArray(int size) {
        return new Order[size];
    }


};

public Order(int covers, int table) {
    super();
    this.covers = covers;
    this.table = table;
    this.items = new ArrayList<MenuItem>();
}

public int getCovers() {
    return covers;
}

public void setCovers(int covers) {
    this.covers = covers;
}

public int getTable() {
    return table;
}

public void setTable(int table) {
    this.table = table;
}

public ArrayList<MenuItem> getItems() {
    return items;
}

public void setItems(ArrayList<MenuItem> items) {
    this.items = items;
}

//add to order
public void addToOrder(MenuItem m){
    items.add(m);
}

//remove from order
public void removeFromOrder(MenuItem m){
    items.remove(m);
}

public Order(Parcel source) {
    this();
    readFromParcel(source);
}

@Override
public int describeContents() {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
    // TODO Auto-generated method stub
    dest.writeInt(covers);
    dest.writeInt(table);
    dest.writeTypedList(items);

}

private  void readFromParcel(Parcel source) {
    // TODO Auto-generated method stub
    covers = source.readInt();
    table = source.readInt();
    items = new ArrayList<MenuItem>();
    source.readTypedList(items,  MenuItem.CREATOR);

}

}

This is how I pass the data between activities:

myOrderBtn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            Toast.makeText(v.getContext(), "myOrderBtn", Toast.LENGTH_SHORT).show();
            Intent i = new Intent(v.getContext(), ViewOrderActivity.class);
            i.putExtra("data", order);
            if(!saved){
            saveOrderState();
            }
            startActivity(i);

        }
    });

and retrieve this way:

public void getOrderData(){
    Intent i = getIntent();
    if(i != null && i.hasExtra("data")){
        order = i.getParcelableExtra("data");
        Toast.makeText(this.getApplicationContext(), "STARTERS recieved order object, covers: " + order.getCovers() + " table no: " + order.getTable() + " order size: " + order.getItems().size(), Toast.LENGTH_SHORT).show();

        if(order.getItems().size() == 0){
            //Toast.makeText(this.getApplicationContext(), "No items added to your order...", Toast.LENGTH_SHORT).show();
        }else{
            for(int j = 0; j != order.getItems().size(); j++){
                dishItems.add(order.getItems().get(j));
            }
        }

        saved = false;

    }
}

Today I learned about the use of a Singleton for global access to data, and I am wondering would it be a good idea to switch to this style of data access? It seems easier to control and a lot tidier with respects to the code.

I'd be interested to see what your opinions on this are. This link here is the pattern I would like to implement:

http://www.devahead.com/blog/2011/06/extending-the-android-application-class-and-dealing-with-singleton/

I should mention, the project is part of my studies in my course. I have to submit my code in a few weeks time, so I am looking for the best way to make it more efficient. So please let me know if you see anything that looks wrong as well!

Javacadabra
  • 5,578
  • 15
  • 84
  • 152
  • 1
    *I am wondering would it be a good idea to switch to [a singleton]?* => 99.9% of the time, it is a [bad idea](http://stackoverflow.com/questions/1448393/singleton-design-pattern-pitfalls). – assylias Jan 22 '13 at 17:24
  • In my opinion both solutions are valid to some extend. Depends on how many activities are using this data. Also if the data gets to big you should go with another solution then singleton or parceable e.g. db. Regarding the singleton you should read this http://code.google.com/p/google-singleton-detector/wiki/WhySingletonsAreControversial – Tobrun Jan 22 '13 at 17:25
  • 1
    aren't you saving your data at some point ? – njzk2 Jan 22 '13 at 17:32
  • @njzk2 Yes, why do you ask? – Javacadabra Jan 22 '13 at 17:35
  • because you probably have a database id of some sort, which you could transmit instead of the object in order to reduce the size of the 'state' – njzk2 Jan 23 '13 at 12:42
  • Nice that you kept "// TODO Auto-generated method stub" in the code – Roel Oct 31 '14 at 10:24

1 Answers1

0

There is very little reason to use Parcelable to move an object around inside a single Linux process. I suggest making your menu a static member of a custom Application object, something like this:

public class MyApplication extends Application {
    private static final List<MenuItem> menu;
    static {
        List<MenuItem> l = new ArrayList<MenuItems>();
        l.add(new MenuItem(...));
        ...
        menu = Collections.unmodifiableList(l);
    }

    ...

    public List<MenuItems> getMenu() { return menu; }

    ....

}

Make sure that the list is immutable, so that you don't have to worry about concurrency issues.

In your manifest:

<application
    android:name=".MyApplication"

... and access it with:

List<MenuItem> menu = ((MyApplication) getApplication()).getMenu();
G. Blake Meike
  • 6,615
  • 3
  • 24
  • 40