【问题标题】:TypeArray in Android - How to store custom objects in xml and retrieve them?Android 中的 TypeArray - 如何在 xml 中存储自定义对象并检索它们?
【发布时间】: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

请帮我解决这个问题。

非常感谢,

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

【问题讨论】:

    标签: android xml custom-component typedarray


    【解决方案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 解析会增加我的应用程序的头痛。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    相关资源
    最近更新 更多