开发者

Java/Android get array from 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 s开发者_开发知识库lower? Can I make this array consistent throughout the app? (But keeping the separate Intent methodology)


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;
    }
}


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.


I could propose two solutions:

  1. You could create a Singleton class that initializes once, reads the data from the XML and stores the stations in a List or a Map. Use a Map if you want to quickly find a station based on its name. The Singleton class will provide methods for retrieving all stations or just one of them.
  2. Create a database table and store the information there. You may need more code, but the advantage will be that you will be able to run more advanced queries.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜