Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java/Android get array from xml

Tags:

java

android

xml

I have a list of longitude and longitude points in an xml file that is used throughout my application. I find my self repeating this code to get points often and think there must be a better way?

    String[] mTempArray = getResources().getStringArray(R.array.stations);
    int len = mTempArray.length;
    mStationArray = new ArrayList<Station>();
    for(int i = 0; i < len; i++){
        Station s = new Station();
        String[] fields = mTempArray[i].split("[\t ]");
        s.setValuesFromArray(fields);
        Log.i("ADD STATION", ""+s);
        mStationArray.add(s);
    }

XML is in the format of:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="stations">
        <item>
            <name>Station name</name>
            <longitude>1111111</longitude>
            <latitude>11111</latitude>
            <code>1</code>
        </item>

And another (possible) problem is that to get just one station I have to get all of them and pull the one I want from the array. Is this going to be considerably slower? Can I make this array consistent throughout the app? (But keeping the separate Intent methodology)

like image 873
Ashley Avatar asked Jan 14 '11 13:01

Ashley


2 Answers

I had the same thought as MilkJug, to use a utility method to create the stations, but I want to offer a slightly different approach: Move as much of the construction logic as possible into the Station class constructor. To keep the example simple, I'm moving the utility method into the Station class as well.

This provides an overall cleaner design, as outside of the Station class itself, your code should never have to deal with a Station object whose construction/initialization steps haven't been fully completed.

(kgiannakakis's suggestion to use a database may be a better way to go if you have a lot of Station objects.)

public class Station {
    private static List<Station> sStationArray = null;

    /**
     * Construct a Station from a specially-encoded String. The String
     * must have all the necessary values for the Station, separated by tabs.
     */ 
    public Station(String fieldString) {
        String[] fields = fieldString.split("[\t ]");

        // For safety, setValuesFromArray() should be declared 'final'.
        // Better yet, you could just move its body into this constructor.
        setValuesFromArray(fields);

        // I'm assuming 'mName' is the name field for the Station
        Log.i("Station", this.mName);
    }

    public static Station getStationArray(Context ctx) {
        if (sStationArray == null) {

            // (Please don't use the prefix 'm' for non-member variables!)
            final String[] tempArray = 
                ctx.getResources().getStringArray(R.array.stations);
            final int len = tempArray.length;

            // Passing the length into the ArrayList constructor (if it's
            // known, or can be guessed at) can be a very simple yet
            // effective optimization. In this case the performance boost
            // will almost certainly **not** be meaningful, but it's
            // helpful to be aware of it.
            sStationArray = new ArrayList<Station>(len);    

            for (int i = 0; i < len; i++) {
                Station s = new Station(tempArray[i]);
                sStationArray.add(s);
            }
        }
        return sStationArray;
    }
}
like image 62
Dan Breslau Avatar answered Sep 28 '22 18:09

Dan Breslau


Why not create a utility method that takes a context as a parameter and returns the station resources? For example:

public class StatUtil {
   private static List<Station> mStationArray = null;

   public static Station getStation(Context ctx) {
    if (mStationArray == null) {
      String[] mTempArray = getResources().getStringArray(R.array.stations);
      int len = mTempArray.length;
      mStationArray = new ArrayList<Station>();
      for(int i = 0; i < len; i++){
        Station s = new Station();
        String[] fields = mTempArray[i].split("[\t ]");
        s.setValuesFromArray(fields);
        Log.i("ADD STATION", ""+s);
        mStationArray.add(s);
      }
    }

    return mStationArray;
  }
}

and call it from your code with:

stationArray = StatUtil.getStation(this);

Repeatedly fetching the stations will be slower than caching them, but not significantly slower unless you are fetching them in a loop. Doing as above will prevent multiple copies from being fetched.

like image 32
MilkJug Avatar answered Sep 28 '22 17:09

MilkJug