一、 引子:你那代码,是“杂乱无章”的菜市场吗?
嘿,哥们儿/姐们儿!有没有经历过这种场景:你正在开发一个美食类App,里面有个下拉菜单,需要展示一堆食材。
你二话不说,在Activity里大手一挥:
String[] ingredients = new String[]{"生抽", "老抽", "蚝油", "陈醋", "料酒", "白糖"};
看起来没问题,对吧?功能跑得呼呼的。
但突然,产品经理屁颠屁颠跑过来说:“大佬,我们再加个‘八角’和‘香叶’呗?” 你眉头一皱,找到那行代码,修改,编译,测试… 麻烦。
这还没完!设计师又说:“我们做个英文版吧!” 你当场石化,难道要再写一个String[] ingredients_en = ...?然后用一堆if-else来判断当前语言?
停!打住!
你的代码,此刻就像一个杂乱无章的菜市场:所有的菜品(数据)都胡堆乱放在过道(代码)里。看着就头大,管理起来更是要命。
而今天我要给你安利的Android数组资源,就是那个帮你把菜市场升级成现代化智能超市的“金牌收纳师”!所有商品分门别类,整齐摆放在货架(res/values目录)上,价签清晰(多语言支持),需要时直接按标签取货,优雅,永不过时。
二、 收纳前的准备:为什么要用数组资源?(灵魂拷问)
在请出这位“收纳师”之前,我们先来个灵魂拷问:我凭什么要用它?
- 告别“硬编码”,维护性UP! UP! UP!
把数据写在代码里,就是我们深恶痛绝的“硬编码”。它让数据和你程序的逻辑紧紧耦合在一起。想象一下,如果你的菜名散落在厨房(代码)的各个角落,改个名字你得翻遍整个厨房。而数组资源把数据统一放在res/values目录下的XML文件里,修改数据就像在仓库管理系统中修改库存,一处修改,全局生效。 - 国际化(i18n)的“神助攻”
这是数组资源乃至所有资源文件的杀手锏。你只需要为不同语言创建不同的arrays.xml文件,比如values-en/arrays.xml(英文)和values-zh/arrays.xml(中文)。系统会根据用户手机的语言设置,自动选择对应的数组。你再也不用写那些令人头秃的if (locale.equals("zh")) ...判断句了。 - 类型安全与编译时检查
在XML中定义的资源,Android构建工具会在编译时进行检查。如果格式错了,编译就通不过,直接在开发阶段就把问题揪出来,避免了运行时才崩溃的尴尬。 - 资源复用,一劳永逸
一个数组资源可以在多个Activity、Fragment、甚至布局文件中被复用。定义一次,到处使用。
所以,不用数组资源,就像有洗衣机偏偏要用手搓,不是勤奋,是… 你懂的。
三、 开始收纳!如何定义你的数组资源?(实战演练)
好了,理论说再多不如一行代码。我们的“收纳仓库”就是res/values目录,通常我们会创建一个名为arrays.xml的文件(名字随便起,但顾名思义最好)。
1. 字符串数组 —— 最常用的“蔬菜区”
这绝对是使用频率最高的数组,专门用来存放一串文字信息。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 定义一个名为 “sauces" 的字符串数组,描述常用调味料 -->
<string-array name="sauces">
<item>生抽</item>
<item>老抽</item>
<item>蚝油</item>
<item>陈醋</item>
<item>料酒</item>
<item>白糖</item>
</string-array>
<!-- 定义一个名为 “cuisines" 的字符串数组,描述菜系 -->
<string-array name="cuisines">
<item>川菜</item>
<item>粤菜</item>
<item>湘菜</item>
<item>鲁菜</item>
</string-array>
</resources>
看,是不是像在货架上贴标签、摆商品一样清晰?
2. 整数数组 —— 精准的“称重区”
当你需要存放一些确切的数字时,比如价格(虽然价格通常用plurals)、难度等级、ID列表等,整数数组就派上用场了。
<resources>
<!-- 定义一个名为 “difficulty_levels” 的整数数组,代表难度等级 -->
<integer-array name="difficulty_levels">
<item>1</item>
<item>2</item>
<item>3</item>
<item>5</item>
<item>8</item>
</integer-array>
</resources>
3. 普通数组 / 类型数组 —— 灵活的“综合商品区”
这个稍微不那么常用,但功能强大。它可以存放混合类型?不,你想多了。它其实是TypedArray,主要用于获取@array/以外的资源ID,比如@dimen, @color等。我们最经典的例子就是用它来定义一组颜色。
首先,在colors.xml里定义颜色:
<resources>
<color name="color_primary">#3F51B5</color>
<color name="color_primary_dark">#303F9F</color>
<color name="color_accent">#FF4081</color>
</resources>
然后,在arrays.xml里用<array>把它们组装起来:
<resources>
<!-- 定义一个名为 “theme_colors” 的普通数组,存放颜色资源 -->
<array name="theme_colors">
<item>@color/color_primary</item>
<item>@color/color_primary_dark</item>
<item>@color/color_accent</item>
</array>
</resources>
注意,这里取出来的是一个TypedArray对象,需要特殊处理。
四、 开张营业!如何在代码中调用它们?(终极奥义)
货都上架了,现在顾客(代码)要来买东西了,怎么卖?
场景1:在Activity/Fragment中(Java版)
假设我们有一个Spinner(下拉列表)要显示那些调味料。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 找到Spinner
Spinner spinnerSauce = findViewById(R.id.spinner_sauce);
// 2. 【核心】从资源中获取字符串数组
// getResources().getStringArray(R.array.数组名)
String[] sauceArray = getResources().getStringArray(R.array.sauces);
// 3. 创建一个Adapter并设置给Spinner
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, sauceArray);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerSauce.setAdapter(adapter);
}
}
场景2:在Activity/Fragment中(Kotlin版)
Kotlin让这个过程更加丝滑:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val spinnerSauce: Spinner = findViewById(R.id.spinner_sauce)
// Kotlin扩展函数,直接resources.getStringArray
val sauceArray = resources.getStringArray(R.array.sauces)
val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, sauceArray)
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
spinnerSauce.adapter = adapter
}
}
场景3:处理整数数组和TypedArray
对于整数数组:
int[] difficultyLevels = getResources().getIntArray(R.array.difficulty_levels);
对于我们刚才定义的theme_colors(TypedArray):
// 获取TypedArray
TypedArray colorArray = getResources().obtainTypedArray(R.array.theme_colors);
// 获取第一个颜色
int firstColor = colorArray.getColor(0, 0); // 0是默认值
// 非常重要!用完后必须回收
colorArray.recycle();
场景4:在布局XML中直接使用!
你没看错,数组资源甚至可以直接在布局文件里使用,最常见的就是给ListView或Spinner设置条目。
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:entries="@array/cuisines" /> <!-- 就是这么简单粗暴! -->
这一行android:entries="@array/cuisines",系统会自动帮你完成我们之前在代码里做的所有Adapter设置工作,非常适合静态数据展示。
五、 走向世界!为数组资源实现国际化
见证奇迹的时刻到了!如何让你的菜市场…啊不,App,支持英文?
- 在
res目录下新建一个values-en文件夹(en代表英文)。 - 在里面也创建一个
arrays.xml文件。 - 将内容翻译成英文。
/res/values-en/arrays.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="sauces">
<item>Light Soy Sauce</item>
<item>Dark Soy Sauce</item>
<item>Oyster Sauce</item>
<item>Vinegar</item>
<item>Cooking Wine</item>
<item>Sugar</item>
</string-array>
<string-array name="cuisines">
<item>Sichuan Cuisine</item>
<item>Cantonese Cuisine</item>
<item>Hunan Cuisine</item>
<item>Shandong Cuisine</item>
</string-array>
</resources>
搞定!当用户手机语言切换为英文时,App会自动加载这个英文版本的数组。是不是魔法?
六、 避坑指南 & 最佳实践
- 不要存放复杂对象:数组资源只能存放基本类型(字符串、整数)或资源引用(颜色、尺寸等)。别想着把自定义类对象塞进去。
TypedArray必须回收:用了obtainTypedArray(),就一定要记得recycle(),否则会引起内存问题。- 大型动态数据不适合:如果你的数组数据来自网络,或者非常大且经常变动,那还是老老实实在代码里处理吧。数组资源更适合静态或相对稳定的数据。
- 命名规范:给数组起个清晰的名字,比如
@array/recipe_steps就比@array/array1好一万倍。
七、 总结
好了,伙计们,我们的“智能超市升级计划”到此就圆满成功了。让我们再回顾一下核心思想:
- 把数据从代码中“请”出来,放进
res/values/arrays.xml这个“中央仓库”。 - 用好
<string-array>、<integer-array>和<array>这三个“货架”,分门别类。 - 在代码中通过
getResources().getXxxArray(R.array.your_array)这个“取货指令”来优雅地获取数据。 - 利用不同
values-xx目录,轻松实现App的国际化,走向全球。
从今天起,告别那个new String[]{...}的“菜市场时代”,拥抱数组资源这个“智能超市”,让你的代码变得整洁、专业、易于维护。你的未来同事(以及三个月后回头看代码的自己),一定会感谢你今天的这个决定!
快去给你的App来一次彻头彻尾的“大扫除”吧!
329

被折叠的 条评论
为什么被折叠?



