-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Users noticed if an app has big a `string.xml` file it affects the app startup time: #4537 The problem is slow XML parsing. Possible ways for optimization: 1) inject text resources direct to the source code 2) convert XMLs to an optimized format to read it faster We selected the second way because texts injected to source code have several problems: - strict limitations on text size - increase compilation and analysation time - affects a class loader and GC > Note: android resources do the same and converts xml values to own `resources.arsc` file Things was done in the PR: 1) added support any XML files in the `values` directory 2) **[BREAKING CHANGE]** added `Res.array` accessor for string-array resources 3) in a final app there won't be original `values*/*.xml` files. There will be converted `values*/*.cvr` files. 4) generated code points on string resources as file -> offset+size 5) string resource cache is by item now (it was by the full xml file before) 6) implemented random access to read CVR files 7) tasks for syncing ios resources to a final app were seriously refactored to support generated resources (CVR files) 8) restriction for 3-party resources plugin were deleted 9) Gradle property `compose.resources.always.generate.accessors` was deleted. It was for internal needs only. Fixes #4537
- Loading branch information
Showing
75 changed files
with
1,747 additions
and
1,808 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
39 changes: 27 additions & 12 deletions
39
.../library/src/androidMain/kotlin/org/jetbrains/compose/resources/ResourceReader.android.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,33 @@ | ||
package org.jetbrains.compose.resources | ||
|
||
import java.io.File | ||
import java.io.InputStream | ||
|
||
private object AndroidResourceReader | ||
internal actual fun getPlatformResourceReader(): ResourceReader = object : ResourceReader { | ||
override suspend fun read(path: String): ByteArray { | ||
val resource = getResourceAsStream(path) | ||
return resource.readBytes() | ||
} | ||
|
||
@OptIn(ExperimentalResourceApi::class) | ||
@InternalResourceApi | ||
actual suspend fun readResourceBytes(path: String): ByteArray { | ||
val classLoader = Thread.currentThread().contextClassLoader ?: AndroidResourceReader.javaClass.classLoader | ||
val resource = classLoader.getResourceAsStream(path) ?: run { | ||
//try to find a font in the android assets | ||
if (File(path).parentFile?.name.orEmpty().startsWith("font")) { | ||
classLoader.getResourceAsStream("assets/$path") | ||
} else null | ||
} ?: throw MissingResourceException(path) | ||
return resource.readBytes() | ||
override suspend fun readPart(path: String, offset: Long, size: Long): ByteArray { | ||
val resource = getResourceAsStream(path) | ||
val result = ByteArray(size.toInt()) | ||
resource.use { input -> | ||
input.skip(offset) | ||
input.read(result, 0, size.toInt()) | ||
} | ||
return result | ||
} | ||
|
||
@OptIn(ExperimentalResourceApi::class) | ||
private fun getResourceAsStream(path: String): InputStream { | ||
val classLoader = Thread.currentThread().contextClassLoader ?: this.javaClass.classLoader | ||
val resource = classLoader.getResourceAsStream(path) ?: run { | ||
//try to find a font in the android assets | ||
if (File(path).parentFile?.name.orEmpty().startsWith("font")) { | ||
classLoader.getResourceAsStream("assets/$path") | ||
} else null | ||
} ?: throw MissingResourceException(path) | ||
return resource | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
121 changes: 121 additions & 0 deletions
121
...es/library/src/commonMain/kotlin/org/jetbrains/compose/resources/PluralStringResources.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package org.jetbrains.compose.resources | ||
|
||
import androidx.compose.runtime.* | ||
import org.jetbrains.compose.resources.plural.PluralCategory | ||
import org.jetbrains.compose.resources.plural.PluralRuleList | ||
|
||
/** | ||
* Represents a quantity string resource in the application. | ||
* | ||
* @param id The unique identifier of the resource. | ||
* @param key The key used to retrieve the string resource. | ||
* @param items The set of resource items associated with the string resource. | ||
*/ | ||
@ExperimentalResourceApi | ||
@Immutable | ||
class PluralStringResource | ||
@InternalResourceApi constructor(id: String, val key: String, items: Set<ResourceItem>) : Resource(id, items) | ||
|
||
/** | ||
* Retrieves the string for the pluralization for the given quantity using the specified quantity string resource. | ||
* | ||
* @param resource The quantity string resource to be used. | ||
* @param quantity The quantity of the pluralization to use. | ||
* @return The retrieved string resource. | ||
* | ||
* @throws IllegalArgumentException If the provided ID or the pluralization is not found in the resource file. | ||
*/ | ||
@ExperimentalResourceApi | ||
@Composable | ||
fun pluralStringResource(resource: PluralStringResource, quantity: Int): String { | ||
val resourceReader = LocalResourceReader.current | ||
val pluralStr by rememberResourceState(resource, quantity, { "" }) { env -> | ||
loadPluralString(resource, quantity, resourceReader, env) | ||
} | ||
return pluralStr | ||
} | ||
|
||
/** | ||
* Loads a string using the specified string resource. | ||
* | ||
* @param resource The string resource to be used. | ||
* @param quantity The quantity of the pluralization to use. | ||
* @return The loaded string resource. | ||
* | ||
* @throws IllegalArgumentException If the provided ID or the pluralization is not found in the resource file. | ||
*/ | ||
@ExperimentalResourceApi | ||
suspend fun getPluralString(resource: PluralStringResource, quantity: Int): String = | ||
loadPluralString(resource, quantity, DefaultResourceReader, getResourceEnvironment()) | ||
|
||
@OptIn(InternalResourceApi::class, ExperimentalResourceApi::class) | ||
private suspend fun loadPluralString( | ||
resource: PluralStringResource, | ||
quantity: Int, | ||
resourceReader: ResourceReader, | ||
environment: ResourceEnvironment | ||
): String { | ||
val resourceItem = resource.getResourceItemByEnvironment(environment) | ||
val item = getStringItem(resourceItem, resourceReader) as StringItem.Plurals | ||
val pluralRuleList = PluralRuleList.getInstance( | ||
environment.language, | ||
environment.region, | ||
) | ||
val pluralCategory = pluralRuleList.getCategory(quantity) | ||
val str = item.items[pluralCategory] | ||
?: item.items[PluralCategory.OTHER] | ||
?: error("Quantity string ID=`${resource.key}` does not have the pluralization $pluralCategory for quantity $quantity!") | ||
return str | ||
} | ||
|
||
/** | ||
* Retrieves the string for the pluralization for the given quantity using the specified quantity string resource. | ||
* | ||
* @param resource The quantity string resource to be used. | ||
* @param quantity The quantity of the pluralization to use. | ||
* @param formatArgs The arguments to be inserted into the formatted string. | ||
* @return The retrieved string resource. | ||
* | ||
* @throws IllegalArgumentException If the provided ID or the pluralization is not found in the resource file. | ||
*/ | ||
@ExperimentalResourceApi | ||
@Composable | ||
fun pluralStringResource(resource: PluralStringResource, quantity: Int, vararg formatArgs: Any): String { | ||
val resourceReader = LocalResourceReader.current | ||
val args = formatArgs.map { it.toString() } | ||
val pluralStr by rememberResourceState(resource, quantity, args, { "" }) { env -> | ||
loadPluralString(resource, quantity, args, resourceReader, env) | ||
} | ||
return pluralStr | ||
} | ||
|
||
/** | ||
* Loads a string using the specified string resource. | ||
* | ||
* @param resource The string resource to be used. | ||
* @param quantity The quantity of the pluralization to use. | ||
* @param formatArgs The arguments to be inserted into the formatted string. | ||
* @return The loaded string resource. | ||
* | ||
* @throws IllegalArgumentException If the provided ID or the pluralization is not found in the resource file. | ||
*/ | ||
@ExperimentalResourceApi | ||
suspend fun getPluralString(resource: PluralStringResource, quantity: Int, vararg formatArgs: Any): String = | ||
loadPluralString( | ||
resource, quantity, | ||
formatArgs.map { it.toString() }, | ||
DefaultResourceReader, | ||
getResourceEnvironment(), | ||
) | ||
|
||
@OptIn(ExperimentalResourceApi::class) | ||
private suspend fun loadPluralString( | ||
resource: PluralStringResource, | ||
quantity: Int, | ||
args: List<String>, | ||
resourceReader: ResourceReader, | ||
environment: ResourceEnvironment | ||
): String { | ||
val str = loadPluralString(resource, quantity, resourceReader, environment) | ||
return str.replaceWithArgs(args) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.