Android支持以占位符的方式,定义字符串。
例如,在xml中定义:

.........
<string name="subtitle_format">%s crimes</string>
.........

在使用该字符串时,可以在运行时动态替换占位符号,例如:

.............
//crimeCount将出现在上面字符中%s的位置
String subtitle = getString(R.string.subtitle_format, "" + crimeCount);
.............

然后,不同的语言对数量的语法规定有不同的规则。
例如一棵树是one tree, 两颗树是two trees。
为了解决后缀的问题,Android引入了plurals 这种资源,其xml定义类似于:

<!--定义到资源文件即可 -->
<plurals name="subtitle_plural"><!--在使用时,可以根据数量来选择不同的字符串--><!--还有zero、few等其它选项--><item quantity="one">%s crime</item><item quantity="other">%s crimes</item>
</plurals>

在代码中的使用规则如下:

..............
int crimeCount = crimeLab.getCrimes().size();
//第一参数为resId,第二个参数为数量,第三个为替换占位符的字符
String subtitle = getResources().getQuantityString(R.plurals.subtitle_plural, crimeCount, crimeCount);
..............

不过plurals的使用,受到系统当前语言(本地化)的限制。

例如,当终端的首选语言为英文时,上面的代码可以很好的工作:

但当系统语言切换为中文时,就会出现问题:

可以看出plurals失效了,为什么会出现这种情况?

为了解释这个问题,只能看看Android源码是如何实现的。
我们从Android 7.0中Resource.java的代码入手:

@NonNull
public String getQuantityString(@PluralsRes int id, int quantity, Object... formatArgs)throws NotFoundException {//容易看出,先根据quantity决定要使用的字符串String raw = getQuantityText(id, quantity).toString();//再进行占位符的替换工作return String.format(mResourcesImpl.getConfiguration().getLocales().get(0), raw,formatArgs);
}@NonNull
public CharSequence getQuantityText(@PluralsRes int id, int quantity)throws NotFoundException {//依赖于ResourceImpl的实现return mResourcesImpl.getQuantityText(id, quantity);
}

跟进ResourceImpl中的getQuantityText函数:

CharSequence getQuantityText(@PluralsRes int id, int quantity) throws NotFoundException {//得到规则PluralRules rule = getPluralRule();//rule.select根据规则,得到quantity对应的QuanitiyCode,即"zero"、"one"、"other"等//之后再根据QuanitiyCode,的到具体的资源文件CharSequence res = mAssets.getResourceBagText(id,attrForQuantityCode(rule.select(quantity)));if (res != null) {return res;}//rule没能找到对应的QuanitiyCode时,就用"other"字段的定义res = mAssets.getResourceBagText(id, ID_OTHER);if (res != null) {return res;}//上面寻找资源文件出问题,就抛出异常throw new NotFoundException("Plural resource ID #0x" + Integer.toHexString(id)+ " quantity=" + quantity+ " item=" + rule.select(quantity));
}

这里我们首先看一下getPluralRule函数:

private PluralRules getPluralRule() {synchronized (sSync) {if (mPluralRule == null) {//单例模式,且和本地化有关,以Locales的第一个配置来初始化规则mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0));}return mPluralRule;}
}

PluralRules的select函数对应的底层实现,在此不作深研究,不同的Locales应该有不同的实现。

在此看看attrForQuantityCode:

private static int attrForQuantityCode(String quantityCode) {switch (quantityCode) {case PluralRules.KEYWORD_ZERO: return 0x01000005;case PluralRules.KEYWORD_ONE:  return 0x01000006;case PluralRules.KEYWORD_TWO:  return 0x01000007;case PluralRules.KEYWORD_FEW:  return 0x01000008;case PluralRules.KEYWORD_MANY: return 0x01000009;default:                       return ID_OTHER;}
}

从上面的代码可以看出,PluralRules的select函数的作用,就是将quantity映射成PluralRules定义的Keyword。
然后attrForQuantityCode将Keyword转化成资源文件能识别的标志。

现在回到我们之前的问题,为什么终端语言为中文时,Plurals string失效?
原因是attrForQuantityCode的结果一直是ID_OTHER,即中文对应PluralRules无法有效将Quantity转化为正确的Keyword。

当然,Google的这种设计并不是Bug,毕竟中文语言环境下,App的显示就应该是中文,本来就没有这种需求。

Android中的string资源占位符及Plurals string相关推荐

  1. Android开发技巧--Application, ListView排列,格式化浮点数,string.xml占位符,动态引用图片...

    一. Application用途 1. Application用途 创建Application时机 : Application在启动的时候会调用Application无参的构造方法创建实例; Appl ...

  2. 【Android 应用开发】Android开发技巧--Application, ListView排列,格式化浮点数,string.xml占位符,动态引用图片

    一. Application用途 1. Application用途 创建Application时机 : Application在启动的时候会调用Application无参的构造方法创建实例; Appl ...

  3. android中的用户资源访问(一)

    2019独角兽企业重金招聘Python工程师标准>>> 这几天要总结一下android开发中的用户资源访问. android中的用户资源存在项目工程中res文件夹下,有字符串.颜色. ...

  4. linux同名文件没有自动替换,linux – bash脚本替换文件中出现的所有占位符

    我正在尝试编写一个bash脚本,用一个同名环境变量替换文件中所有出现的占位符.举个例子,如果我有一个像下面这样的文件-- This is an {{VAR1}} {{VAR2}}. It should ...

  5. android 换行符 编码_android中的常见的占位符及转义字符

    常见的几种占位符 String.format%d: 整数类型(十进制),如:99,其中%04d表示在前面补0,即0099 %f: 浮点类型,如:99.99 其中%.2f表示保留两位小数 %s: 字符串 ...

  6. SQL算法中的变量使用占位符动态赋值

    需求: 1.每张表的SQL算法配置到数据库的配置表中 2.SQL算法中的条件统一使用占位符填充 3.当执行sql时需要将查询出来的SQL算法中的占位符动态赋值 一.真实案例还原 这里拿表进行演示 1. ...

  7. Android中的Searchview以及SearchableDictionary项目和plurals详解

    Android4.0之后,Android内置了一个搜索控件,配合ActionBar上面的搜索按钮,相当不错好看,这次使用了下,觉得很不错. 这个搜索的好处在于你点击后,他会自动弹出个搜索框,输入内容后 ...

  8. Android中从assets资源中读取图片文件并保存到内部存储器并加载显示在ImageView中

    场景 Android系统为每个新设计的程序提供了/assets目录,这个目录保存的文件可以打包在程序里./res和/assets的不同点是,android不为/assets下的文件生成ID.如果使用/ ...

  9. Android中通过数组资源文件xml与适配器两种方式给ListView列表视图设置数据源

    场景 实现效果如下 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获取编程相关电子书.教程推送与免费下载. 实现 将布局改 ...

最新文章

  1. https原理与实践
  2. 内存管理模拟程序c语言,C语言 内存管理详解
  3. 一.js高级(4)-函数调用-this指向-其他参数
  4. python手机软件-Python爬虫:抓取手机APP的数据
  5. java heap space 解决方法_Java静态方法/变量,非静态方法/变量的区别,今天一并帮你解决
  6. java cas是原子性的么_Java 并发编程:AQS 的原子性如何保证
  7. python函数每日一讲 - cmp(x,y)
  8. 我的linux复习之一密码修改
  9. Java 8 终于支持 Docker !
  10. 什么是hibernate N+1查询
  11. Linux学习篇之权限管理
  12. Atitit.远程文件技术 webdav ftp scp ssh-sftp http nfs smb 的区别与总结
  13. 人民日报刊发浪潮集团董事长孙丕恕署名文章:更好实现数据共享
  14. pytorch关系抽取框架OpenNRE源码解读与实践:PCNN ATT
  15. 利用BS爬取单词音标
  16. Facebook创始人简介
  17. 单模光电转换器怎么接_光纤收发器及其连接方式图解!
  18. requests爬虫搜狗微信公众号
  19. 设置电脑 保护视力 还有桌面默认颜色
  20. 标准柯西分布_柯西分布没有数学期望

热门文章

  1. 故障:不能登录到“纳税人权益平台”
  2. 利用Python轻松实现图片相似度对比(一)
  3. 语文同步学 | (家长必读)期末复习重点,不看准丢分
  4. 【优化求解】飞蛾扑火算法(MFO)matlab源码
  5. indexof java 返回值_Java之indexOf()方法
  6. Consul 命令(CLI)
  7. 苹果人脸识别再低一点_从人脸到人脸识别,行业背后神秘职业揭秘
  8. “勇者立”——浅析数字化孪生的转型
  9. 基于MATLAB实现PCA人脸识别
  10. 浮点数的表示 —— 基本格式、规格化、表示范围