Fixed slow search because of Genres, and also added Playlists to Search results, Don't worry that won't slow the search.

This commit is contained in:
Prathamesh More 2022-01-29 00:28:16 +05:30
parent 5c1a88b32b
commit 010b771373
5 changed files with 73 additions and 73 deletions

View file

@ -96,11 +96,11 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
view.doOnPreDraw { view.doOnPreDraw {
startPostponedEnterTransition() startPostponedEnterTransition()
} }
libraryViewModel.getFabMargin().observe(viewLifecycleOwner, { libraryViewModel.getFabMargin().observe(viewLifecycleOwner) {
binding.keyboardPopup.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.keyboardPopup.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = it bottomMargin = it
} }
}) }
KeyboardVisibilityEvent.setEventListener(requireActivity(), viewLifecycleOwner) { KeyboardVisibilityEvent.setEventListener(requireActivity(), viewLifecycleOwner) {
if (it) { if (it) {
binding.keyboardPopup.isGone = true binding.keyboardPopup.isGone = true
@ -192,6 +192,7 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
R.id.chip_albums -> Filter.ALBUMS R.id.chip_albums -> Filter.ALBUMS
R.id.chip_album_artists -> Filter.ALBUM_ARTISTS R.id.chip_album_artists -> Filter.ALBUM_ARTISTS
R.id.chip_genres -> Filter.GENRES R.id.chip_genres -> Filter.GENRES
R.id.chip_playlists -> Filter.PLAYLISTS
else -> Filter.NO_FILTER else -> Filter.NO_FILTER
} }
} }
@ -245,6 +246,7 @@ enum class Filter {
ALBUMS, ALBUMS,
ALBUM_ARTISTS, ALBUM_ARTISTS,
GENRES, GENRES,
PLAYLISTS,
NO_FILTER NO_FILTER
} }

View file

@ -16,19 +16,19 @@ package code.name.monkey.retromusic.repository
import android.content.ContentResolver import android.content.ContentResolver
import android.database.Cursor import android.database.Cursor
import android.net.Uri
import android.provider.BaseColumns import android.provider.BaseColumns
import android.provider.MediaStore.Audio.Genres import android.provider.MediaStore.Audio.Genres
import code.name.monkey.retromusic.Constants.IS_MUSIC import code.name.monkey.retromusic.Constants.IS_MUSIC
import code.name.monkey.retromusic.Constants.baseProjection import code.name.monkey.retromusic.Constants.baseProjection
import code.name.monkey.retromusic.extensions.getLong import code.name.monkey.retromusic.extensions.getLong
import code.name.monkey.retromusic.extensions.getString
import code.name.monkey.retromusic.extensions.getStringOrNull import code.name.monkey.retromusic.extensions.getStringOrNull
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.PreferenceUtil
interface GenreRepository { interface GenreRepository {
fun genres(query: String): List<Genre>
fun genres(): List<Genre> fun genres(): List<Genre>
fun songs(genreId: Long): List<Song> fun songs(genreId: Long): List<Song>
@ -41,6 +41,10 @@ class RealGenreRepository(
private val songRepository: RealSongRepository private val songRepository: RealSongRepository
) : GenreRepository { ) : GenreRepository {
override fun genres(query: String): List<Genre> {
return getGenresFromCursor(makeGenreCursor(query))
}
override fun genres(): List<Genre> { override fun genres(): List<Genre> {
return getGenresFromCursor(makeGenreCursor()) return getGenresFromCursor(makeGenreCursor())
} }
@ -57,18 +61,23 @@ class RealGenreRepository(
return songRepository.song(makeGenreSongCursor(genreId)) return songRepository.song(makeGenreSongCursor(genreId))
} }
private fun getSongCount(genreId: Long): Int {
contentResolver.query(
Genres.Members.getContentUri("external", genreId),
null,
null,
null,
null
).use {
return it?.count ?: 0
}
}
private fun getGenreFromCursor(cursor: Cursor): Genre { private fun getGenreFromCursor(cursor: Cursor): Genre {
val id = cursor.getLong(Genres._ID) val id = cursor.getLong(Genres._ID)
val name = cursor.getStringOrNull(Genres.NAME) val name = cursor.getStringOrNull(Genres.NAME)
val songCount = songs(id).size val songCount = getSongCount(id)
return Genre(id, name ?: "", songCount) return Genre(id, name ?: "", songCount)
}
private fun getGenreFromCursorWithOutSongs(cursor: Cursor): Genre {
val id = cursor.getLong(Genres._ID)
val name = cursor.getString(Genres.NAME)
return Genre(id, name, -1)
} }
private fun getSongsWithNoGenre(): List<Song> { private fun getSongsWithNoGenre(): List<Song> {
@ -77,28 +86,6 @@ class RealGenreRepository(
return songRepository.songs(songRepository.makeSongCursor(selection, null)) return songRepository.songs(songRepository.makeSongCursor(selection, null))
} }
private fun hasSongsWithNoGenre(): Boolean {
val allSongsCursor = songRepository.makeSongCursor(null, null)
val allSongsWithGenreCursor = makeAllSongsWithGenreCursor()
if (allSongsCursor == null || allSongsWithGenreCursor == null) {
return false
}
val hasSongsWithNoGenre = allSongsCursor.count > allSongsWithGenreCursor.count
allSongsCursor.close()
allSongsWithGenreCursor.close()
return hasSongsWithNoGenre
}
private fun makeAllSongsWithGenreCursor(): Cursor? {
println(Genres.EXTERNAL_CONTENT_URI.toString())
return contentResolver.query(
Uri.parse("content://media/external/audio/genres/all/members"),
arrayOf(Genres.Members.AUDIO_ID), null, null, null
)
}
private fun makeGenreSongCursor(genreId: Long): Cursor? { private fun makeGenreSongCursor(genreId: Long): Cursor? {
return try { return try {
contentResolver.query( contentResolver.query(
@ -121,37 +108,13 @@ class RealGenreRepository(
val genre = getGenreFromCursor(cursor) val genre = getGenreFromCursor(cursor)
if (genre.songCount > 0) { if (genre.songCount > 0) {
genres.add(genre) genres.add(genre)
} else {
// try to remove the empty genre from the media store
try {
contentResolver.delete(
Genres.EXTERNAL_CONTENT_URI,
Genres._ID + " == " + genre.id,
null
)
} catch (e: Exception) {
e.printStackTrace()
}
} }
} while (cursor.moveToNext()) } while (cursor.moveToNext())
} }
cursor.close()
} }
return genres return genres
} }
private fun getGenresFromCursorForSearch(cursor: Cursor?): List<Genre> {
val genres = mutableListOf<Genre>()
if (cursor != null && cursor.moveToFirst()) {
do {
genres.add(getGenreFromCursorWithOutSongs(cursor))
} while (cursor.moveToNext())
}
cursor?.close()
return genres
}
private fun makeGenreCursor(): Cursor? { private fun makeGenreCursor(): Cursor? {
val projection = arrayOf(Genres._ID, Genres.NAME) val projection = arrayOf(Genres._ID, Genres.NAME)
return try { return try {
@ -166,4 +129,19 @@ class RealGenreRepository(
return null return null
} }
} }
private fun makeGenreCursor(query: String): Cursor? {
val projection = arrayOf(Genres._ID, Genres.NAME)
return try {
contentResolver.query(
Genres.EXTERNAL_CONTENT_URI,
projection,
Genres.NAME + " = ?",
arrayOf(query),
PreferenceUtil.genreSortOrder
)
} catch (e: SecurityException) {
return null
}
}
} }

View file

@ -16,6 +16,7 @@ package code.name.monkey.retromusic.repository
import android.content.Context import android.content.Context
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.db.PlaylistEntity
import code.name.monkey.retromusic.fragments.search.Filter import code.name.monkey.retromusic.fragments.search.Filter
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
@ -29,20 +30,23 @@ class RealSearchRepository(
private val roomRepository: RoomRepository, private val roomRepository: RoomRepository,
private val genreRepository: GenreRepository, private val genreRepository: GenreRepository,
) { ) {
fun searchAll(context: Context, query: String?, filter: Filter): MutableList<Any> { suspend fun searchAll(context: Context, query: String?, filter: Filter): MutableList<Any> {
val results = mutableListOf<Any>() val results = mutableListOf<Any>()
if (query.isNullOrEmpty()) return results if (query.isNullOrEmpty()) return results
query.let { searchString -> query.let { searchString ->
/** Songs **/
val songs: List<Song> = if (filter == Filter.SONGS || filter == Filter.NO_FILTER) { val songs: List<Song> = if (filter == Filter.SONGS || filter == Filter.NO_FILTER) {
songRepository.songs(searchString) songRepository.songs(searchString)
} else { } else {
emptyList() emptyList()
} }
if (songs.isNotEmpty()) { if (songs.isNotEmpty()) {
results.add(context.resources.getString(R.string.songs)) results.add(context.resources.getString(R.string.songs))
results.addAll(songs) results.addAll(songs)
} }
/** Artists **/
val artists: List<Artist> = val artists: List<Artist> =
if (filter == Filter.ARTISTS || filter == Filter.NO_FILTER) { if (filter == Filter.ARTISTS || filter == Filter.NO_FILTER) {
artistRepository.artists(searchString) artistRepository.artists(searchString)
@ -53,6 +57,8 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.artists)) results.add(context.resources.getString(R.string.artists))
results.addAll(artists) results.addAll(artists)
} }
/** Albums **/
val albums: List<Album> = if (filter == Filter.ALBUMS || filter == Filter.NO_FILTER) { val albums: List<Album> = if (filter == Filter.ALBUMS || filter == Filter.NO_FILTER) {
albumRepository.albums(searchString) albumRepository.albums(searchString)
} else { } else {
@ -62,6 +68,8 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.albums)) results.add(context.resources.getString(R.string.albums))
results.addAll(albums) results.addAll(albums)
} }
/** Album-Artists **/
val albumArtists: List<Artist> = val albumArtists: List<Artist> =
if (filter == Filter.ALBUM_ARTISTS || filter == Filter.NO_FILTER) { if (filter == Filter.ALBUM_ARTISTS || filter == Filter.NO_FILTER) {
artistRepository.albumArtists(searchString) artistRepository.albumArtists(searchString)
@ -72,11 +80,10 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.album_artist)) results.add(context.resources.getString(R.string.album_artist))
results.addAll(albumArtists) results.addAll(albumArtists)
} }
/** Genres **/
val genres: List<Genre> = if (filter == Filter.GENRES || filter == Filter.NO_FILTER) { val genres: List<Genre> = if (filter == Filter.GENRES || filter == Filter.NO_FILTER) {
genreRepository.genres().filter { genre -> genreRepository.genres(query)
genre.name.lowercase()
.contains(searchString.lowercase())
}
} else { } else {
emptyList() emptyList()
} }
@ -84,14 +91,21 @@ class RealSearchRepository(
results.add(context.resources.getString(R.string.genres)) results.add(context.resources.getString(R.string.genres))
results.addAll(genres) results.addAll(genres)
} }
/* val playlist = roomRepository.playlists().filter { playlist ->
playlist.playlistName.toLowerCase(Locale.getDefault()) /** Playlists **/
.contains(searchString.toLowerCase(Locale.getDefault())) val playlist: List<PlaylistEntity> =
} if (filter == Filter.PLAYLISTS || filter == Filter.NO_FILTER) {
if (playlist.isNotEmpty()) { roomRepository.playlists().filter { playlist ->
results.add(context.getString(R.string.playlists)) playlist.playlistName.lowercase().contains(searchString.lowercase())
results.addAll(playlist) }
}*/ } else {
emptyList()
}
if (playlist.isNotEmpty()) {
results.add(context.getString(R.string.playlists))
results.addAll(playlist)
}
} }
return results return results
} }

View file

@ -117,6 +117,13 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/genres" /> android:text="@string/genres" />
<com.google.android.material.chip.Chip
android:id="@+id/chip_playlists"
style="@style/SearchChipStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/playlists" />
</com.google.android.material.chip.ChipGroup> </com.google.android.material.chip.ChipGroup>
</HorizontalScrollView> </HorizontalScrollView>

View file

@ -207,7 +207,6 @@
<item name="android:textSize">16sp</item> <item name="android:textSize">16sp</item>
<item name="checkedIconEnabled">true</item> <item name="checkedIconEnabled">true</item>
<item name="chipEndPadding">10dp</item> <item name="chipEndPadding">10dp</item>
<item name="chipIconEnabled">true</item>
<item name="chipMinHeight">40dp</item> <item name="chipMinHeight">40dp</item>
<item name="chipStartPadding">10dp</item> <item name="chipStartPadding">10dp</item>
</style> </style>