如何在 Android Jetpack Compose 中使用字符串资源? 字符串字符串数组复数数量字符串关于重组的说明

问题描述

让我们拥有以下 strings.xml 资源文件

<resources>
    <!-- basic string -->
    <string name="app_name">My Playground</string>

    <!-- basic string with an argument -->
    <string name="greeting">Hello %!</string>

    <!-- plural string -->
    <plurals name="likes">
        <item quantity="one">%1d like</item>
        <item quantity="other">%1d likes</item>
    </plurals>

    <!-- string array -->
    <string-array name="planets">
        <item>Earth</item>
        <item>Mars</item>
    </string-array>
</resources>

如何在 Jetpack Compose 中使用这些资源?

解决方法

androidx.compose.ui.res 包包含加载字符串资源和其他资源类型的函数。

字符串

您可以使用 stringResource() 函数获取字符串,例如:

...
import androidx.compose.ui.res.stringResource

@Composable
fun StringResourceExample() {
  Text(
    // a string without arguments
    text = stringResource(R.string.app_name)
  )

  Text(
    // a string with arguments
    text = stringResource(R.string.greeting,"World")
  )
}

字符串数组

可以使用stringArrayResource()函数获得:

val planets = stringArrayResource(R.array.planets_array)

复数(数量字符串)

从 compose 1.0.0-alpha10 开始,没有用于获取复数资源的内置函数,但是您可以通过 LocalContext 获取 android 上下文,并像在视图中一样使用它-基于应用程序。如果您创建自己的类似于其他资源函数的函数(例如 Jetcaster compose sample 所做的),那就更好了:

// PluralResources.kt

package com.myapp.util

import androidx.annotation.PluralsRes
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext

@Composable
fun quantityStringResource(@PluralsRes id: Int,quantity: Int,vararg formatArgs: Any): String {
    return LocalContext.current.resources.getQuantityString(id,quantity,*formatArgs)
}

所以你可以用同样的方式使用它:

val likes = quantityStringResource(R.plurals.likes,10,10)

关于重组的说明

如您所知,在组合中,可组合函数在 recomposition 期间每秒可能会被重新执行数百次。如果你构建的字符串不是微不足道的,需要一些计算,最好将计算结果remember,这样就不会在每次重新组合时重新执行。例如:

...

import androidx.compose.runtime.remember

@Composable
fun BirthdayDateComposable(username: String,dateMillis: Long) {
  // formatDate() function will be executed only if dateMillis value 
  // is changed,otherwise the remembered value will be used
  val dateStr = remember(dateMillis) {
    formatDate(dateMillis)
  }

  Text(
    text = stringResource(R.string.birthday_date,dateStr)
  )
}