Optimize Imageloader to not create empty MusicDirectory.Entries

This commit is contained in:
tzugen 2021-09-12 14:03:39 +02:00
parent 611539be55
commit 28097bf325
No known key found for this signature in database
GPG Key ID: 61E9C34BC10EC930
3 changed files with 71 additions and 39 deletions

View File

@ -14,8 +14,8 @@ import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView.S
import java.text.Collator
import org.moire.ultrasonic.R
import org.moire.ultrasonic.domain.ArtistOrIndex
import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.imageloader.ImageLoader
import org.moire.ultrasonic.util.FileUtil
import org.moire.ultrasonic.util.Util
/**
@ -59,13 +59,14 @@ class ArtistRowAdapter(
if (Util.getShouldShowArtistPicture()) {
holder.coverArt.visibility = View.VISIBLE
val key = FileUtil.getArtistArtKey(itemList[listPosition].name, false)
imageLoader.loadImage(
holder.coverArt,
MusicDirectory.Entry("-1").apply {
coverArt = holder.coverArtId
artist = itemList[listPosition].name
},
false, 0, R.drawable.ic_contact_picture
view = holder.coverArt,
id = holder.coverArtId,
key = key,
large = false,
size = 0,
defaultResourceId = R.drawable.ic_contact_picture
)
} else {
holder.coverArt.visibility = View.GONE

View File

@ -93,10 +93,27 @@ class ImageLoader(
defaultResourceId: Int = R.drawable.unknown_album
) {
val id = entry?.coverArt
val key = FileUtil.getAlbumArtKey(entry, large)
loadImage(view, id, key, large, size, defaultResourceId)
}
/**
* Load the cover of a given entry into an ImageView
*/
@JvmOverloads
@Suppress("LongParameterList", "ComplexCondition")
fun loadImage(
view: View?,
id: String?,
key: String?,
large: Boolean,
size: Int,
defaultResourceId: Int = R.drawable.unknown_album
) {
val requestedSize = resolveSize(size, large)
if (id != null && id.isNotEmpty() && view is ImageView) {
val key = FileUtil.getAlbumArtKey(entry, large)
if (id != null && key != null && id.isNotEmpty() && view is ImageView) {
val request = ImageRequest.CoverArt(
id, key, view, requestedSize,
placeHolderDrawableRes = defaultResourceId,

View File

@ -41,6 +41,8 @@ object FileUtil {
private val TITLE_WITH_TRACK = Pattern.compile("^\\d\\d-.*")
const val SUFFIX_LARGE = ".jpeg"
const val SUFFIX_SMALL = ".jpeg-small"
private const val UNNAMED = "unnamed"
private val permissionUtil = KoinJavaComponent.inject<PermissionUtil>(
PermissionUtil::class.java
)
@ -50,7 +52,7 @@ object FileUtil {
// Do not generate new name for offline files. Offline files will have their Path as their Id.
if (!TextUtils.isEmpty(song.id)) {
if (song.id.startsWith(dir!!.absolutePath)) return File(song.id)
if (song.id.startsWith(dir.absolutePath)) return File(song.id)
}
// Generate a file name for the song
@ -66,7 +68,7 @@ object FileUtil {
fileName.append(track).append('-')
}
}
fileName.append(fileSystemSafe(song.title!!)).append('.')
fileName.append(fileSystemSafe(song.title)).append('.')
if (!TextUtils.isEmpty(song.transcodedSuffix)) {
fileName.append(song.transcodedSuffix)
} else {
@ -76,7 +78,7 @@ object FileUtil {
}
@JvmStatic
fun getPlaylistFile(server: String?, name: String): File {
fun getPlaylistFile(server: String?, name: String?): File {
val playlistDir = getPlaylistDirectory(server)
return File(playlistDir, String.format(Locale.ROOT, "%s.m3u", fileSystemSafe(name)))
}
@ -89,7 +91,8 @@ object FileUtil {
return playlistDir
}
fun getPlaylistDirectory(server: String?): File {
@JvmStatic
fun getPlaylistDirectory(server: String? = null): File {
val playlistDir: File
if (server != null) {
playlistDir = File(playlistDirectory, server)
@ -105,7 +108,7 @@ object FileUtil {
* @param entry The album entry
* @return File object. Not guaranteed that it exists
*/
fun getAlbumArtFile(entry: MusicDirectory.Entry?): File? {
fun getAlbumArtFile(entry: MusicDirectory.Entry): File {
val albumDir = getAlbumDirectory(entry)
return getAlbumArtFile(albumDir)
}
@ -117,20 +120,30 @@ object FileUtil {
* @return String The hash key
*/
fun getAlbumArtKey(entry: MusicDirectory.Entry?, large: Boolean): String? {
if (entry == null) return null
val albumDir = getAlbumDirectory(entry)
return getAlbumArtKey(albumDir, large)
}
/**
* Get the cache key for a given artist
* @param name The artist name
* @param large Whether to get the key for the large or the default image
* @return String The hash key
*/
fun getArtistArtKey(name: String?, large: Boolean): String {
val artist = fileSystemSafe(name)
val dir = File(String.format(Locale.ROOT, "%s/%s/%s", musicDirectory.path, artist, UNNAMED))
return getAlbumArtKey(dir, large)
}
/**
* Get the cache key for a given album entry
* @param albumDir The album directory
* @param large Whether to get the key for the large or the default image
* @return String The hash key
*/
private fun getAlbumArtKey(albumDir: File?, large: Boolean): String? {
if (albumDir == null) {
return null
}
private fun getAlbumArtKey(albumDir: File, large: Boolean): String {
val suffix = if (large) SUFFIX_LARGE else SUFFIX_SMALL
return String.format(Locale.ROOT, "%s%s", Util.md5Hex(albumDir.path), suffix)
}
@ -149,12 +162,11 @@ object FileUtil {
* @param albumDir The album directory
* @return File object. Not guaranteed that it exists
*/
fun getAlbumArtFile(albumDir: File?): File? {
@JvmStatic
fun getAlbumArtFile(albumDir: File): File {
val albumArtDir = albumArtDirectory
val key = getAlbumArtKey(albumDir, true)
return if (key == null) {
null
} else File(albumArtDir, key)
return File(albumArtDir, key)
}
/**
@ -162,6 +174,7 @@ object FileUtil {
* @param cacheKey The key (== the filename)
* @return File object. Not guaranteed that it exists
*/
@JvmStatic
fun getAlbumArtFile(cacheKey: String?): File? {
val albumArtDir = albumArtDirectory
return if (cacheKey == null) {
@ -177,10 +190,7 @@ object FileUtil {
return albumArtDir
}
fun getAlbumDirectory(entry: MusicDirectory.Entry?): File? {
if (entry == null) {
return null
}
fun getAlbumDirectory(entry: MusicDirectory.Entry): File {
val dir: File
if (!TextUtils.isEmpty(entry.path)) {
val f = File(fileSystemSafeDir(entry.path))
@ -193,10 +203,10 @@ object FileUtil {
)
)
} else {
val artist = fileSystemSafe(entry.artist!!)
var album = fileSystemSafe(entry.album!!)
if ("unnamed" == album) {
album = fileSystemSafe(entry.title!!)
val artist = fileSystemSafe(entry.artist)
var album = fileSystemSafe(entry.album)
if (UNNAMED == album) {
album = fileSystemSafe(entry.title)
}
dir = File(String.format(Locale.ROOT, "%s/%s/%s", musicDirectory.path, artist, album))
}
@ -225,11 +235,13 @@ object FileUtil {
// GetExternalFilesDir will always return a directory which Ultrasonic
// can access without any extra privileges.
@JvmStatic
val ultrasonicDirectory: File?
get() = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) File(
Environment.getExternalStorageDirectory(),
"Android/data/org.moire.ultrasonic"
) else UApp.applicationContext().getExternalFilesDir(null)
val ultrasonicDirectory: File
get() {
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) File(
Environment.getExternalStorageDirectory(),
"Android/data/org.moire.ultrasonic"
) else UApp.applicationContext().getExternalFilesDir(null)!!
}
// After Android M, the location of the files must be queried differently.
// GetExternalFilesDir will always return a directory which Ultrasonic
@ -237,6 +249,7 @@ object FileUtil {
@JvmStatic
val defaultMusicDirectory: File
get() = getOrCreateDirectory("music")
@JvmStatic
val musicDirectory: File
get() {
@ -285,11 +298,12 @@ object FileUtil {
* @param name The filename in question.
* @return The filename with special characters replaced by hyphens.
*/
private fun fileSystemSafe(name: String): String {
var filename = name
if (filename.trim { it <= ' ' }.isEmpty()) {
return "unnamed"
private fun fileSystemSafe(name: String?): String {
if (name == null || name.trim { it <= ' ' }.isEmpty()) {
return UNNAMED
}
var filename: String = name
for (s in FILE_SYSTEM_UNSAFE) {
filename = filename.replace(s, "-")
}