Android 中的 TypeArray - 如何在 xml 中存储自定义对象并检索它们?

Posted

技术标签:

【中文标题】Android 中的 TypeArray - 如何在 xml 中存储自定义对象并检索它们?【英文标题】:TypeArray in Android - How to store custom objects in xml and retrieve them? 【发布时间】:2011-10-10 02:46:01 【问题描述】:

我有一门课

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;
    

并希望将此类的对象存储在类似 android 的 TypeArray xml 中

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

我想如何在我的 Activty 类中访问这个数组,比如

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**);

但我不知道如何实现这一点。 我试过 customArr.getString(0);但它给了我一切都像字符串一样 阿尔巴尼亚 al @drawable/al

请帮我解决这个问题。

非常感谢,

谨此致以最诚挚的问候, 伊山

【问题讨论】:

【参考方案1】:

Here is example。阅读并查看 TypedArray 的方法,例如 get...(),例如 getDrawable(int index)。我建议将相同类型的项目保留在单独的数组中。

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

编辑:

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;

【讨论】:

感谢 Dziobas 的重播。实际上我这样做并创建了三个不同的数组,但它似乎是有线的,所以我只是想找到一种方法,我可以将所有数据存储在单个 xml 中。而不是 getDrawable(int index) 我想做一些类似 getCountryVO(int index) 的事情有没有办法实现这一点? 您可以在getCountryVO(int index) 中实现它,只需在里面输入代码即可从数组中获取国家、代码和标志。 但是在 getResources().obtainTypedArray("array_name") 的时候,它不可能做 getResources().obtainTypedArray("array_name").getCountryVO(index)。那么请您指导我如何从 TypedArray 获取特定索引处的特定对象? 您好,谢谢!这是您在新 CountryVO 中提供的一个很好的解决方案。但是你知道这有两个缺点,如果我错了,请纠正我。 1.我们需要管理3个不同的xml,难度大且容易出错。 2. 在 CountryVO 中获取所有这 3 个数组以仅创建一个对象,从内存管理的角度来看,这似乎很奇怪。这就是为什么我想在一个数组中管理所有这些信息。目前我选择其他解决方案,即在 Map 上创建并将我所有的 CountryVO 放入其中。 我刚刚回答了你的问题。正如我提供的链接一样,它位于一个 xml 文件中。我不确定,但是资源中的 xmls 是在应用程序二进制文件中构建的,因此它可能会被编译器优化。它应该比在 SAX 中解析更快。当然你也可以把它放在java类的静态数组中。不知道你有什么要求。祝你好运。【参考方案2】:

当我需要可以在代码之外编辑的自定义对象时,我通常使用 json,这对于人类和(可能)机器来说都更容易阅读;)

您还可以拥有比简单数组更复杂的对象。

/res/raw 文件夹中创建一个 json 文件(例如 countries.json)后,如下所示:

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

你可以像这样加载数据:

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

如果您不想手动进行解析,您也可以使用gson,它可以帮助您传递对象,然后以惰性方式加载可绘制对象... ;)

编辑:添加实用程序类

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

希望对你有帮助

【讨论】:

我收到一个错误cannot resolve method convertStreamToString。我尝试导入所有可用选项 非常正确。我忘了。这是一个实用程序类。我会尝试找到代码。尽管功能是将流的输出复制到一个新字符串中,但还是有解决方案的。 另外,如果你可以使用 Gson,我会推荐它。更少的低级代码 是的,我最终以其他方式进行了操作。谢谢:)【参考方案3】:

您需要先解析 xml,然后再尝试将其存储在您的类中。我建议你使用 SAX API,你可以找到一个关于它的教程here.希望这会有所帮助!

【讨论】:

嗨,Kenny,谢谢你的回复,但我们不能用 android xml 和 getResources().obtailtypearray() 来解决这个问题吗?显式 xml 解析会增加我的应用程序的头痛。

以上是关于Android 中的 TypeArray - 如何在 xml 中存储自定义对象并检索它们?的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 类型数组TypeArray

从Objective C中的NSArray转换时如何比较String?

从cypress中的函数返回数组

JavaScript模拟表单(带数组的复杂数据结构)提交

HTML5 Blob与ArrayBufferTypeArray和字符串String之间转换

如何比较在Objective C中从NSArray转换的String?