mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-18 04:30:48 +01:00
Optimize Imageloader to not create empty MusicDirectory.Entries
This commit is contained in:
parent
611539be55
commit
28097bf325
@ -14,8 +14,8 @@ import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView.S
|
|||||||
import java.text.Collator
|
import java.text.Collator
|
||||||
import org.moire.ultrasonic.R
|
import org.moire.ultrasonic.R
|
||||||
import org.moire.ultrasonic.domain.ArtistOrIndex
|
import org.moire.ultrasonic.domain.ArtistOrIndex
|
||||||
import org.moire.ultrasonic.domain.MusicDirectory
|
|
||||||
import org.moire.ultrasonic.imageloader.ImageLoader
|
import org.moire.ultrasonic.imageloader.ImageLoader
|
||||||
|
import org.moire.ultrasonic.util.FileUtil
|
||||||
import org.moire.ultrasonic.util.Util
|
import org.moire.ultrasonic.util.Util
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,13 +59,14 @@ class ArtistRowAdapter(
|
|||||||
|
|
||||||
if (Util.getShouldShowArtistPicture()) {
|
if (Util.getShouldShowArtistPicture()) {
|
||||||
holder.coverArt.visibility = View.VISIBLE
|
holder.coverArt.visibility = View.VISIBLE
|
||||||
|
val key = FileUtil.getArtistArtKey(itemList[listPosition].name, false)
|
||||||
imageLoader.loadImage(
|
imageLoader.loadImage(
|
||||||
holder.coverArt,
|
view = holder.coverArt,
|
||||||
MusicDirectory.Entry("-1").apply {
|
id = holder.coverArtId,
|
||||||
coverArt = holder.coverArtId
|
key = key,
|
||||||
artist = itemList[listPosition].name
|
large = false,
|
||||||
},
|
size = 0,
|
||||||
false, 0, R.drawable.ic_contact_picture
|
defaultResourceId = R.drawable.ic_contact_picture
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
holder.coverArt.visibility = View.GONE
|
holder.coverArt.visibility = View.GONE
|
||||||
|
@ -93,10 +93,27 @@ class ImageLoader(
|
|||||||
defaultResourceId: Int = R.drawable.unknown_album
|
defaultResourceId: Int = R.drawable.unknown_album
|
||||||
) {
|
) {
|
||||||
val id = entry?.coverArt
|
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)
|
val requestedSize = resolveSize(size, large)
|
||||||
|
|
||||||
if (id != null && id.isNotEmpty() && view is ImageView) {
|
if (id != null && key != null && id.isNotEmpty() && view is ImageView) {
|
||||||
val key = FileUtil.getAlbumArtKey(entry, large)
|
|
||||||
val request = ImageRequest.CoverArt(
|
val request = ImageRequest.CoverArt(
|
||||||
id, key, view, requestedSize,
|
id, key, view, requestedSize,
|
||||||
placeHolderDrawableRes = defaultResourceId,
|
placeHolderDrawableRes = defaultResourceId,
|
||||||
|
@ -41,6 +41,8 @@ object FileUtil {
|
|||||||
private val TITLE_WITH_TRACK = Pattern.compile("^\\d\\d-.*")
|
private val TITLE_WITH_TRACK = Pattern.compile("^\\d\\d-.*")
|
||||||
const val SUFFIX_LARGE = ".jpeg"
|
const val SUFFIX_LARGE = ".jpeg"
|
||||||
const val SUFFIX_SMALL = ".jpeg-small"
|
const val SUFFIX_SMALL = ".jpeg-small"
|
||||||
|
private const val UNNAMED = "unnamed"
|
||||||
|
|
||||||
private val permissionUtil = KoinJavaComponent.inject<PermissionUtil>(
|
private val permissionUtil = KoinJavaComponent.inject<PermissionUtil>(
|
||||||
PermissionUtil::class.java
|
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.
|
// Do not generate new name for offline files. Offline files will have their Path as their Id.
|
||||||
if (!TextUtils.isEmpty(song.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
|
// Generate a file name for the song
|
||||||
@ -66,7 +68,7 @@ object FileUtil {
|
|||||||
fileName.append(track).append('-')
|
fileName.append(track).append('-')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fileName.append(fileSystemSafe(song.title!!)).append('.')
|
fileName.append(fileSystemSafe(song.title)).append('.')
|
||||||
if (!TextUtils.isEmpty(song.transcodedSuffix)) {
|
if (!TextUtils.isEmpty(song.transcodedSuffix)) {
|
||||||
fileName.append(song.transcodedSuffix)
|
fileName.append(song.transcodedSuffix)
|
||||||
} else {
|
} else {
|
||||||
@ -76,7 +78,7 @@ object FileUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun getPlaylistFile(server: String?, name: String): File {
|
fun getPlaylistFile(server: String?, name: String?): File {
|
||||||
val playlistDir = getPlaylistDirectory(server)
|
val playlistDir = getPlaylistDirectory(server)
|
||||||
return File(playlistDir, String.format(Locale.ROOT, "%s.m3u", fileSystemSafe(name)))
|
return File(playlistDir, String.format(Locale.ROOT, "%s.m3u", fileSystemSafe(name)))
|
||||||
}
|
}
|
||||||
@ -89,7 +91,8 @@ object FileUtil {
|
|||||||
return playlistDir
|
return playlistDir
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPlaylistDirectory(server: String?): File {
|
@JvmStatic
|
||||||
|
fun getPlaylistDirectory(server: String? = null): File {
|
||||||
val playlistDir: File
|
val playlistDir: File
|
||||||
if (server != null) {
|
if (server != null) {
|
||||||
playlistDir = File(playlistDirectory, server)
|
playlistDir = File(playlistDirectory, server)
|
||||||
@ -105,7 +108,7 @@ object FileUtil {
|
|||||||
* @param entry The album entry
|
* @param entry The album entry
|
||||||
* @return File object. Not guaranteed that it exists
|
* @return File object. Not guaranteed that it exists
|
||||||
*/
|
*/
|
||||||
fun getAlbumArtFile(entry: MusicDirectory.Entry?): File? {
|
fun getAlbumArtFile(entry: MusicDirectory.Entry): File {
|
||||||
val albumDir = getAlbumDirectory(entry)
|
val albumDir = getAlbumDirectory(entry)
|
||||||
return getAlbumArtFile(albumDir)
|
return getAlbumArtFile(albumDir)
|
||||||
}
|
}
|
||||||
@ -117,20 +120,30 @@ object FileUtil {
|
|||||||
* @return String The hash key
|
* @return String The hash key
|
||||||
*/
|
*/
|
||||||
fun getAlbumArtKey(entry: MusicDirectory.Entry?, large: Boolean): String? {
|
fun getAlbumArtKey(entry: MusicDirectory.Entry?, large: Boolean): String? {
|
||||||
|
if (entry == null) return null
|
||||||
val albumDir = getAlbumDirectory(entry)
|
val albumDir = getAlbumDirectory(entry)
|
||||||
return getAlbumArtKey(albumDir, large)
|
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
|
* Get the cache key for a given album entry
|
||||||
* @param albumDir The album directory
|
* @param albumDir The album directory
|
||||||
* @param large Whether to get the key for the large or the default image
|
* @param large Whether to get the key for the large or the default image
|
||||||
* @return String The hash key
|
* @return String The hash key
|
||||||
*/
|
*/
|
||||||
private fun getAlbumArtKey(albumDir: File?, large: Boolean): String? {
|
private fun getAlbumArtKey(albumDir: File, large: Boolean): String {
|
||||||
if (albumDir == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val suffix = if (large) SUFFIX_LARGE else SUFFIX_SMALL
|
val suffix = if (large) SUFFIX_LARGE else SUFFIX_SMALL
|
||||||
return String.format(Locale.ROOT, "%s%s", Util.md5Hex(albumDir.path), suffix)
|
return String.format(Locale.ROOT, "%s%s", Util.md5Hex(albumDir.path), suffix)
|
||||||
}
|
}
|
||||||
@ -149,12 +162,11 @@ object FileUtil {
|
|||||||
* @param albumDir The album directory
|
* @param albumDir The album directory
|
||||||
* @return File object. Not guaranteed that it exists
|
* @return File object. Not guaranteed that it exists
|
||||||
*/
|
*/
|
||||||
fun getAlbumArtFile(albumDir: File?): File? {
|
@JvmStatic
|
||||||
|
fun getAlbumArtFile(albumDir: File): File {
|
||||||
val albumArtDir = albumArtDirectory
|
val albumArtDir = albumArtDirectory
|
||||||
val key = getAlbumArtKey(albumDir, true)
|
val key = getAlbumArtKey(albumDir, true)
|
||||||
return if (key == null) {
|
return File(albumArtDir, key)
|
||||||
null
|
|
||||||
} else File(albumArtDir, key)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,6 +174,7 @@ object FileUtil {
|
|||||||
* @param cacheKey The key (== the filename)
|
* @param cacheKey The key (== the filename)
|
||||||
* @return File object. Not guaranteed that it exists
|
* @return File object. Not guaranteed that it exists
|
||||||
*/
|
*/
|
||||||
|
@JvmStatic
|
||||||
fun getAlbumArtFile(cacheKey: String?): File? {
|
fun getAlbumArtFile(cacheKey: String?): File? {
|
||||||
val albumArtDir = albumArtDirectory
|
val albumArtDir = albumArtDirectory
|
||||||
return if (cacheKey == null) {
|
return if (cacheKey == null) {
|
||||||
@ -177,10 +190,7 @@ object FileUtil {
|
|||||||
return albumArtDir
|
return albumArtDir
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAlbumDirectory(entry: MusicDirectory.Entry?): File? {
|
fun getAlbumDirectory(entry: MusicDirectory.Entry): File {
|
||||||
if (entry == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val dir: File
|
val dir: File
|
||||||
if (!TextUtils.isEmpty(entry.path)) {
|
if (!TextUtils.isEmpty(entry.path)) {
|
||||||
val f = File(fileSystemSafeDir(entry.path))
|
val f = File(fileSystemSafeDir(entry.path))
|
||||||
@ -193,10 +203,10 @@ object FileUtil {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val artist = fileSystemSafe(entry.artist!!)
|
val artist = fileSystemSafe(entry.artist)
|
||||||
var album = fileSystemSafe(entry.album!!)
|
var album = fileSystemSafe(entry.album)
|
||||||
if ("unnamed" == album) {
|
if (UNNAMED == album) {
|
||||||
album = fileSystemSafe(entry.title!!)
|
album = fileSystemSafe(entry.title)
|
||||||
}
|
}
|
||||||
dir = File(String.format(Locale.ROOT, "%s/%s/%s", musicDirectory.path, artist, album))
|
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
|
// GetExternalFilesDir will always return a directory which Ultrasonic
|
||||||
// can access without any extra privileges.
|
// can access without any extra privileges.
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val ultrasonicDirectory: File?
|
val ultrasonicDirectory: File
|
||||||
get() = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) File(
|
get() {
|
||||||
Environment.getExternalStorageDirectory(),
|
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) File(
|
||||||
"Android/data/org.moire.ultrasonic"
|
Environment.getExternalStorageDirectory(),
|
||||||
) else UApp.applicationContext().getExternalFilesDir(null)
|
"Android/data/org.moire.ultrasonic"
|
||||||
|
) else UApp.applicationContext().getExternalFilesDir(null)!!
|
||||||
|
}
|
||||||
|
|
||||||
// After Android M, the location of the files must be queried differently.
|
// After Android M, the location of the files must be queried differently.
|
||||||
// GetExternalFilesDir will always return a directory which Ultrasonic
|
// GetExternalFilesDir will always return a directory which Ultrasonic
|
||||||
@ -237,6 +249,7 @@ object FileUtil {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
val defaultMusicDirectory: File
|
val defaultMusicDirectory: File
|
||||||
get() = getOrCreateDirectory("music")
|
get() = getOrCreateDirectory("music")
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val musicDirectory: File
|
val musicDirectory: File
|
||||||
get() {
|
get() {
|
||||||
@ -285,11 +298,12 @@ object FileUtil {
|
|||||||
* @param name The filename in question.
|
* @param name The filename in question.
|
||||||
* @return The filename with special characters replaced by hyphens.
|
* @return The filename with special characters replaced by hyphens.
|
||||||
*/
|
*/
|
||||||
private fun fileSystemSafe(name: String): String {
|
private fun fileSystemSafe(name: String?): String {
|
||||||
var filename = name
|
if (name == null || name.trim { it <= ' ' }.isEmpty()) {
|
||||||
if (filename.trim { it <= ' ' }.isEmpty()) {
|
return UNNAMED
|
||||||
return "unnamed"
|
|
||||||
}
|
}
|
||||||
|
var filename: String = name
|
||||||
|
|
||||||
for (s in FILE_SYSTEM_UNSAFE) {
|
for (s in FILE_SYSTEM_UNSAFE) {
|
||||||
filename = filename.replace(s, "-")
|
filename = filename.replace(s, "-")
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user