Android开发:如何传递点语法后的变量片段以简化代码调用?
解决方案
针对R.string资源的场景
要通过资源名称片段(如whatever_text)获取对应字符串,可以用反射实现,但需注意混淆和异常处理:
fun passStringResName(resName: String) { val resId = try { // 通过反射从R.string类中获取对应字段的int值 R.string::class.java.getField(resName).getInt(null) } catch (e: NoSuchFieldException) { // 资源不存在时返回默认提示 android.R.string.unknownName } catch (e: IllegalAccessException) { android.R.string.unknownName } val targetString = getString(resId) // 后续业务逻辑 }
调用方式:
passStringResName("whatever_text")
注意事项
- 混淆处理:开启ProGuard时需保留
R.string的字段名,避免被混淆:-keepclassmembers class **.R$string { public static <fields>; } - 性能:反射存在轻微性能开销,频繁调用时需权衡。
通用场景(如NavigationDestination.xxx.screenRoute)
这类自定义类的静态属性/常量,优先用类型安全的封装方案(枚举/密封类),比反射更可靠:
方案1:用密封类封装路由
sealed class ScreenRoute(val route: String) { object Home : ScreenRoute("home_screen") object Profile : ScreenRoute("profile_screen") // 新增页面时直接在这里添加 } // 接收路由的函数 fun passScreenRoute(route: ScreenRoute) { val targetRoute = route.route // 后续业务逻辑 }
调用方式:
passScreenRoute(ScreenRoute.Home)
方案2:用枚举封装(适合固定数量的场景)
enum class ScreenRoute(val route: String) { HOME("home_screen"), PROFILE("profile_screen") }
调用方式和密封类一致,优势是天然支持遍历、序列化等特性。
若必须用字符串片段(不推荐)
如果无法修改现有结构,可通过反射获取静态属性:
inline fun <reified T> getStaticPropertyValue(propertyName: String): String? { return try { val field = T::class.java.getField(propertyName) val targetObj = field.get(null) // 假设目标属性是screenRoute,根据实际调整 targetObj.javaClass.getField("screenRoute").get(targetObj) as? String } catch (e: Exception) { null // 处理属性不存在的情况 } }
调用方式:
val route = getStaticPropertyValue<NavigationDestination>("whateverDestination")
同样需要在混淆规则中保留目标类的字段:
-keepclassmembers class com.yourpackage.NavigationDestination { public static <fields>; }
内容的提问来源于stack exchange,提问作者Drocchio
相关产品推荐
相关产品推荐

