Kotlin开发Android骰子应用如何动态格式化调用资源ID替代多条件判断
实现方案
下面提供3种常用的可行优化方案,你可以根据自己的需求选择:
方案1:动态通过资源名获取资源ID(最符合你动态格式化调用的需求)
Android 提供了Resources.getIdentifier()方法,可以通过资源名称字符串、资源类型、包名动态查找对应的资源ID,完全不需要写条件判断。
优化后的rollDice代码如下:
private fun rollDice() { val dice = Dice(6) val diceRoll = dice.roll() val diceImage: ImageView = findViewById(R.id.imageView) // 按命名规则动态生成资源名 val resName = "dice_$diceRoll" // 动态查找对应drawable的资源ID val resId = resources.getIdentifier(resName, "drawable", packageName) // 加兜底逻辑避免资源不存在导致崩溃 diceImage.setImageResource(if (resId != 0) resId else R.drawable.dice_1) }
优缺点说明:
- 优点:代码极简,后续如果要扩展骰子面数,只需要添加对应命名的drawable资源即可,不需要修改逻辑代码
- 缺点:内部通过反射查找资源,有微小的性能损耗,资源名写错时编译期不会报错,运行时才会出现找不到资源的问题
方案2:预定义资源映射表(性能最优,编译安全)
提前把点数和对应的资源ID的映射关系存在集合中,使用时直接通过点数取值,不需要动态查找,性能最好,且编译期就能检查资源是否存在。
首先在MainActivity中定义成员变量存储映射关系:
// 下标对应骰子点数,索引0空置不用 private val diceDrawableIds = intArrayOf(0, R.drawable.dice_1, R.drawable.dice_2, R.drawable.dice_3, R.drawable.dice_4, R.drawable.dice_5, R.drawable.dice_6)
然后修改rollDice方法:
private fun rollDice() { val dice = Dice(6) val diceRoll = dice.roll() val diceImage: ImageView = findViewById(R.id.imageView) diceImage.setImageResource(diceDrawableIds[diceRoll]) }
优缺点说明:
- 优点:性能最高,编译期就能校验资源存在,不会出现运行时找不到资源的问题
- 缺点:扩展骰子面数时需要手动修改映射表添加新的资源ID
方案3:用when表达式替换if-else(逻辑最直观,适合固定面数场景)
如果不想用上面两种方案,只是想把冗余的if-else简化,可以用Kotlin的when表达式,代码更简洁易读:
private fun rollDice() { val dice = Dice(6) val diceRoll = dice.roll() val diceImage: ImageView = findViewById(R.id.imageView) val drawableId = when(diceRoll) { 1 -> R.drawable.dice_1 2 -> R.drawable.dice_2 3 -> R.drawable.dice_3 4 -> R.drawable.dice_4 5 -> R.drawable.dice_5 else -> R.drawable.dice_6 } diceImage.setImageResource(drawableId) }
优缺点说明:
- 优点:逻辑直观清晰,编译期安全,不需要额外的反射或者预定义集合
- 缺点:面数较多时代码会变长,扩展需要手动添加分支
额外优化提示
你可以将ImageView和Button的实例提到类成员变量的位置,避免每次触发点击事件都重复执行findViewById,提升性能:
class MainActivity : AppCompatActivity() { private lateinit var diceImage: ImageView private lateinit var rollButton: Button override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) diceImage = findViewById(R.id.imageView) rollButton = findViewById(R.id.button) rollButton.setOnClickListener { rollDice() } } // 后续rollDice方法中不需要再执行findViewById }
内容的提问来源于stack exchange,提问作者yonatan goldin
相关产品推荐
相关产品推荐

