all: do not do work on static initialization

Try to lazily initialize certain static variables that do work (like
Regex) to speed up initialization time.
This commit is contained in:
Alexander Capehart 2023-05-11 13:04:07 -06:00
parent c98ca8712f
commit a5176d6209
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
9 changed files with 30 additions and 34 deletions

View file

@ -568,8 +568,8 @@ private inline fun <T : Music, K> compareByDynamic(
}
/**
* Utility function to create a [Comparator] that sorts in ascending order based on the
* given [Comparator], with a selector based on the item itself.
* Utility function to create a [Comparator] that sorts in ascending order based on the given
* [Comparator], with a selector based on the item itself.
*
* @param comparator The [Comparator] to wrap.
* @return A new [Comparator] with the specified configuration.
@ -581,8 +581,8 @@ private fun <T : Music> compareBy(comparator: Comparator<T>): Comparator<T> =
/**
* A [Comparator] that chains several other [Comparator]s together to form one comparison.
*
* @param comparators The [Comparator]s to chain. These will be iterated through in order
* during a comparison, with the first non-equal result becoming the result.
* @param comparators The [Comparator]s to chain. These will be iterated through in order during a
* comparison, with the first non-equal result becoming the result.
*/
private class MultiComparator<T>(vararg comparators: Comparator<T>) : Comparator<T> {
private val _comparators = comparators
@ -656,8 +656,8 @@ private class BasicComparator<T : Music> private constructor() : Comparator<T> {
}
/**
* A [Comparator] that compares two possibly null values. Values will be considered lesser
* if they are null, and greater if they are non-null.
* A [Comparator] that compares two possibly null values. Values will be considered lesser if they
* are null, and greater if they are non-null.
*/
private class NullableComparator<T : Comparable<T>> private constructor() : Comparator<T?> {
override fun compare(a: T?, b: T?) =

View file

@ -23,6 +23,8 @@ import android.content.pm.PackageManager
import androidx.core.content.ContextCompat
import java.util.*
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import org.oxycblt.auxio.R
@ -32,12 +34,9 @@ import org.oxycblt.auxio.music.device.RawSong
import org.oxycblt.auxio.music.fs.MediaStoreExtractor
import org.oxycblt.auxio.music.metadata.TagExtractor
import org.oxycblt.auxio.music.user.UserLibrary
import org.oxycblt.auxio.util.fallible
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.logW
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
/**
* Primary manager of music information and loading.
@ -293,7 +292,7 @@ constructor(
val incompleteSongs = Channel<RawSong>(Channel.UNLIMITED)
val mediaStoreJob =
worker.scope.tryAsync {
mediaStoreExtractor.consume(query, cache, incompleteSongs, completeSongs) }.also {
mediaStoreExtractor.consume(query, cache, incompleteSongs, completeSongs)
incompleteSongs.close()
}
val metadataJob =
@ -326,7 +325,10 @@ constructor(
worker.scope.tryAsync(Dispatchers.Main) {
deviceLibraryFactory.create(rawSongs).also { deviceLibraryChannel.send(it) }
}
val userLibraryJob = worker.scope.tryAsync { userLibraryFactory.read(deviceLibraryChannel) }
val userLibraryJob =
worker.scope.tryAsync {
userLibraryFactory.read(deviceLibraryChannel).also { deviceLibraryChannel.close() }
}
if (cache == null || cache.invalidated) {
cacheRepository.writeCache(rawSongs)
}

View file

@ -185,9 +185,10 @@ class Date private constructor(private val tokens: List<Int>) : Comparable<Date>
* A [Regex] that can parse a variable-precision ISO-8601 timestamp. Derived from
* https://github.com/quodlibet/mutagen
*/
private val ISO8601_REGEX =
private val ISO8601_REGEX by lazy {
Regex(
"""^(\d{4})([-.](\d{2})([-.](\d{2})([T ](\d{2})([:.](\d{2})([:.](\d{2})(Z)?)?)?)?)?)?$""")
}
/**
* Create a [Date] from a year component.

View file

@ -35,7 +35,7 @@ sealed interface Name : Comparable<Name> {
/**
* A logical first character that can be used to collate a sorted list of music.
*
* TODO: Move this to the home view
* TODO: Move this to the home package
*/
val thumb: String
@ -87,7 +87,7 @@ sealed interface Name : Comparable<Name> {
final override val thumb: String
get() =
// TODO: Remove these checks once you have real unit testing
// TODO: Remove these safety checks once you have real unit testing
sortTokens
.firstOrNull()
?.run { collationKey.sourceString.firstOrNull() }
@ -114,8 +114,7 @@ sealed interface Name : Comparable<Name> {
*
* @param raw The raw name obtained from the music item
* @param sort The raw sort name obtained from the music item
* @param musicSettings [MusicSettings] required to obtain user-preferred sorting
* configurations
* @param musicSettings [MusicSettings] required for name configuration.
*/
fun from(raw: String, sort: String?, musicSettings: MusicSettings): Known =
if (musicSettings.intelligentSorting) {
@ -145,7 +144,7 @@ sealed interface Name : Comparable<Name> {
}
private val COLLATOR: Collator = Collator.getInstance().apply { strength = Collator.PRIMARY }
private val PUNCT_REGEX = Regex("[\\p{Punct}+]")
private val PUNCT_REGEX by lazy { Regex("[\\p{Punct}+]") }
/**
* Plain [Name.Known] implementation that is internationalization-safe.
@ -215,6 +214,6 @@ private data class IntelligentKnownName(override val raw: String, override val s
}
companion object {
private val TOKEN_REGEX = Regex("(\\d+)|(\\D+)")
private val TOKEN_REGEX by lazy { Regex("(\\d+)|(\\D+)") }
}
}

View file

@ -209,7 +209,7 @@ private fun String.parseId3v1Genre(): String? {
* A [Regex] that implements parsing for ID3v2's genre format. Derived from mutagen:
* https://github.com/quodlibet/mutagen
*/
private val ID3V2_GENRE_RE = Regex("((?:\\((\\d+|RX|CR)\\))*)(.+)?")
private val ID3V2_GENRE_RE by lazy { Regex("((?:\\((\\d+|RX|CR)\\))*)(.+)?") }
/**
* Parse an ID3v2 integer genre field, which has support for multiple genre values and combined

View file

@ -47,6 +47,11 @@ private constructor(
*/
inline fun edit(edits: MutableList<Song>.() -> Unit) = edit(songs.toMutableList().apply(edits))
override fun equals(other: Any?) =
other is PlaylistImpl && uid == other.uid && songs == other.songs
override fun hashCode() = 31 * uid.hashCode() + songs.hashCode()
companion object {
/**
* Create a new instance with a novel UID.

View file

@ -294,6 +294,6 @@ constructor(
* Matches non-float information from ReplayGain adjustments. Derived from vanilla music:
* https://github.com/vanilla-music/vanilla
*/
val REPLAYGAIN_ADJUSTMENT_FILTER_REGEX = Regex("[^\\d.-]")
val REPLAYGAIN_ADJUSTMENT_FILTER_REGEX by lazy { Regex("[^\\d.-]") }
}
}

View file

@ -125,7 +125,8 @@ class SearchEngineImpl @Inject constructor(@ApplicationContext private val conte
* Converts the output of [Normalizer] to remove any junk characters added by it's
* replacements, alongside punctuation.
*/
val NORMALIZE_POST_PROCESSING_REGEX =
val NORMALIZE_POST_PROCESSING_REGEX by lazy {
Regex("(\\p{InCombiningDiacriticalMarks}+)|(\\p{Punct})")
}
}
}

View file

@ -34,18 +34,6 @@ fun <T> unlikelyToBeNull(value: T?) =
value!!
}
/**
* Maps a try expression to a [Result].
* @param block The code to execute
* @return A [Result] representing the outcome of [block]'s execution.
*/
inline fun <reified R> fallible(block: () -> R) =
try {
Result.success(block())
} catch (e: Exception) {
Result.failure(e)
}
/**
* Aliases a check to ensure that the given number is non-zero.
*