22

I have a class like

public class CountryVO {
    private String countryCode;
    private String countryName;
    private Drawable countryFlag;
    
    public String getCountryCode() {
        return countryCode;
    }
    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }
    public String getCountryName() {
        return countryName;
    }
    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }
    public Drawable getCountryFlag() {
        return countryFlag;
    }
    public void setCountryFlag(Drawable countryFlag) {
        this.countryFlag = countryFlag;
    }
}

and want to store objects of this class in an TypeArray xml of android like

<resources>
    <array name="custom_arr">
        <item>
            <countryName>Albania</countryName>
            <countryCode>al</countryCode>
            <countryFlag>@drawable/al</countryFlag>
        </item>
        <item>
            <countryName>Algeria</countryName>
            <countryCode>dz</countryCode>
            <countryFlag>@drawable/dz</countryFlag>
        </item>
        <item>
            <countryName>American Samoa</countryName>
            <countryCode>as</countryCode>
            <countryFlag>@drawable/as</countryFlag>
        </item>
        <item>
            <countryName>India</countryName>
            <countryCode>in</countryCode>
            <countryFlag>@drawable/in</countryFlag>
        </item>
        <item>
            <countryName>South Africa</countryName>
            <countryCode>sa</countryCode>
            <countryFlag>@drawable/sa</countryFlag>
        </item>
    </array>
</resources>

how i want to access this array in my Activty class like

TypedArray customArr = getResources().obtainTypedArray(R.array.country_arr);
    CountryVO vo = new CountryVO();
    vo.setCountryName(**value from array come here for first element's countryName attribute**);
    vo.setCountryCode(**value from array come here for first element's countryCode attribute**);
    vo.setCountryFlag(**value from array come here for first element's countryFlag attribute**);

But i don't to how to achieve this. I tried customArr.getString(0); but it gives me everything as string like Albania al @drawable/al

Please help me to solve this problem.

Thanks a lot in advance,

With best regards, Ishan

Sourab Sharma
  • 2,940
  • 1
  • 25
  • 38
Ishan
  • 303
  • 2
  • 4
  • 11

3 Answers3

16

Here is example. Read it and look at the methods of TypedArray like get...() for example getDrawable(int index). I would suggest to keep items of the same type in separated arrays.

<array name="country">
    <item>Albania</item>
    <item>Algeria</item>
    <item>American Samoa</item>
</array>
<array name="code">
    <item>al</item>
    <item>dz</item>
    <item>as</item>
</array>
<array name="flag">
    <item>@drawable/dz</item>
    <item>@drawable/al</item>
    <item>@drawable/as</item>
</array>

EDIT:

public CountryVO getCountryVO(int index){
    Resources resources = getResources();
    TypedArray country = resources.obtainTypedArray(R.array.country);
    TypedArray code = resources.obtainTypedArray(R.array.code);
    TypedArray flag = resources.obtainTypedArray(R.array.flag);

    CountryVO vo = new CountryVO(country.getString(index), code.getString(index), flag.getDrawable(index));

    country.recycle();
    code.recycle();
    flag.recycle();

    return vo;
}
pawelzieba
  • 16,082
  • 3
  • 46
  • 72
  • Thank you Dziobas for your replay. Actually i did that and created three different arrays but it seems wired so I am just looking to find a way where I can store all the data in single xml. and rather than getDrawable(int index) i want to do something like getCountryVO(int index) is there any way to achieve this ? – Ishan Jul 21 '11 at 11:52
  • You can implement it in `getCountryVO(int index)`, just put inside code to get country, code and flag from arrays. – pawelzieba Jul 21 '11 at 12:09
  • but at the time of getResources().obtainTypedArray("array_name") its not possible to do getResources().obtainTypedArray("array_name").getCountryVO(index). so will you please guide me how can a get a particular object at specific index from TypedArray ? – Ishan Jul 21 '11 at 13:41
  • 1
    Hi, Thank you! This is a nice solution you provided in new CountryVO. But you know there are two downsides of this, plz correct me if I am wrong. 1. We need to manage 3 different xmls, which is difficult and error prone. 2. Obtaining all these 3 array in CountryVO for creating just one object, its seems odd from memory management point of view. That's why I want to manage all these information in only one array. At present i go for the other solution i.e. created on Map and put all my CountryVOs in it. – Ishan Jul 22 '11 at 07:03
  • I've just answered your question. As is in link that I provided, it is in one xml file. I'm not sure, but xmls in resources are built in application binary, therefore it maybe optimized by compiler. It should be faster than parsing in SAX. Of course you can put it in static array in java class also. I don't know what requirements you have. Good luck. – pawelzieba Jul 22 '11 at 08:02
16

When I need custom objects that can be edited outside code i generally use json which is easier to read for both humans and (possibly) machines ;)

You can also have more complex objects than with simple arrays.

Once you create a json file (e.g. countries.json) in the /res/raw folder like this:

{ "countries" : [
    {"country" : "Albania", "countryCode" : "al" },
    {"country" : "Algeria", "countryCode" : "dz"},
    {"country" : "American Samoa", "countryCode" : "as"},
    {"country" : "India", "countryCode" : "in"},
    {"country" : "South Africa", "countryCode" : "sa"}
]}

you can load the data like this:

InputStream jsonStream = context.getResources().openRawResource(R.raw.countries);
JSONObject jsonObject = new JSONObject(Strings.convertStreamToString(jsonStream));
JSONArray jsonContries = jsonObject.getJSONArray("countries");
List<CountryVO> countries = new ArrayList<CountryVO>();
for (int i = 0, m = countries.length(); i < m; i++) {
    JSONObject jsonCountry = countries.getJSONObject(i);
    CountryVO country = new CountryVO();
    country.setCountryName(jsonCountry.getString("country"));
    String co = jsonCountry.getString("countryCode");
    country.setCountryCode(co);
    try {
        Class<?> drawableClass = com.example.R.drawable.class; // replace package
        Field drawableField = drawableClass.getField(co);
        int drawableId = (Integer)drawableField.get(null);
        Drawable drawable = getResources().getDrawable(drawableId);
        country.setCountryFlag(drawable);
     } catch (Exception e) {
         // report exception
     }
     countries.add(country);
}

If you don't want to do the parsing manually you can also use gson which helps you to pass the objects and then load the drawables in a lazy fashion... ;)

Edit: Added utility class

public String convertStreamToString(InputStream is) { 
  Scanner s = new Scanner(is).useDelimiter("\\A");
  return s.hasNext() ? s.next() : "";
}

Hope it helps

pablisco
  • 14,027
  • 4
  • 48
  • 70
  • I am getting an error `cannot resolve method convertStreamToString`. I tried importing all available options – wick.ed Jun 23 '17 at 20:56
  • Very true. I forgot. It's a utility class. I'll try to find the code. Although the functionality is copying the output of the stream into a new string, there are solutions out there. – pablisco Jun 24 '17 at 08:39
  • Also, if you can use Gson I would recommend it. Less low level code – pablisco Jun 24 '17 at 08:40
  • Yeah I ended up doing it other way. Thanks :) – wick.ed Jun 24 '17 at 15:26
0

You need to parse the xml before trying to store it in your class. I would recommend that you use the SAX API, you can find a tutorial on it here. Hope this helps!

Kenny
  • 5,522
  • 2
  • 18
  • 29
  • Hey Kenny,Thank you for your reply, but can't we achieve this working around with android xml and getResources().obtailtypearray(); explicit xml parsing will increase headache of my application. – Ishan Jul 21 '11 at 11:54