From 3134e313a3838b6af4d83959012f948cefd55951 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Tue, 18 Aug 2020 15:33:59 -0600 Subject: [PATCH] Move MusicRepository initialization to coroutine Move the init call to MusicRepostiory to a coroutine so that it doesnt stop the UI thread. --- .../oxycblt/auxio/library/LibraryFragment.kt | 10 ++++-- .../oxycblt/auxio/library/LibraryViewModel.kt | 33 +++++++++++++++++-- .../oxycblt/auxio/music/MusicRepository.kt | 29 +++++++++------- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt index de8be2284..0e0b5a4f1 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt @@ -10,14 +10,18 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import org.oxycblt.auxio.R import org.oxycblt.auxio.databinding.FragmentLibraryBinding -import org.oxycblt.auxio.music.MusicRepository class LibraryFragment : Fragment() { // Lazily initiate the ViewModel when its first referenced. // Not because this does anything, it just looks nicer. private val libraryModel: LibraryViewModel by lazy { - ViewModelProvider(this).get(LibraryViewModel::class.java) + ViewModelProvider( + this, + LibraryViewModel.Factory( + requireActivity().application + ) + ).get(LibraryViewModel::class.java) } override fun onCreateView( @@ -29,7 +33,7 @@ class LibraryFragment : Fragment() { inflater, R.layout.fragment_library, container, false ) - MusicRepository.getInstance().init(requireActivity().application) + libraryModel Log.d(this::class.simpleName, "Fragment created.") diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt index 786c7dc9b..f76213535 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt @@ -1,13 +1,42 @@ package org.oxycblt.auxio.library +import android.app.Application import android.util.Log import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import org.oxycblt.auxio.music.MusicRepository -class LibraryViewModel() : ViewModel() { +class LibraryViewModel(private val app: Application) : ViewModel() { - // TODO: Implement music data in ViewModel + private val viewModelJob = Job() + private val ioScope = CoroutineScope( + Dispatchers.IO + ) init { + startMusicRepo() + Log.d(this::class.simpleName, "ViewModel created.") } + + // TODO: Temp function, remove when LoadingFragment is added + private fun startMusicRepo() { + ioScope.launch { + MusicRepository.getInstance().init(app) + } + } + + class Factory(private val application: Application) : ViewModelProvider.Factory { + @Suppress("unchecked_cast") + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(LibraryViewModel::class.java)) { + return LibraryViewModel(application) as T + } + throw IllegalArgumentException("Unknown ViewModel class") + } + } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt index c88ef4557..f41052fb1 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicRepository.kt @@ -4,7 +4,6 @@ import android.app.Application import android.content.ContentResolver import android.content.ContentUris import android.database.Cursor -import android.graphics.Bitmap import android.media.MediaMetadataRetriever import android.provider.MediaStore import android.provider.MediaStore.Audio.AudioColumns @@ -47,13 +46,15 @@ class MusicRepository { app.contentResolver ) + Log.i(this::class.simpleName, "Starting music search...") + // Index music files from shared storage musicCursor?.use { cursor -> val idIndex = cursor.getColumnIndexOrThrow(AudioColumns._ID) val displayIndex = cursor.getColumnIndexOrThrow(AudioColumns.DISPLAY_NAME) - var retriever = MediaMetadataRetriever() + val retriever = MediaMetadataRetriever() while (cursor.moveToNext()) { val id = cursor.getLong(idIndex) @@ -83,18 +84,23 @@ class MusicRepository { val genre = retriever.extractMetadata( MediaMetadataRetriever.METADATA_KEY_GENRE ) - - val year = (retriever.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_YEAR - ) ?: "0").toInt() + + val year = ( + retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_YEAR + ) ?: "0" + ).toInt() // Track is formatted as X/0, so trim off the /0 part to parse // the track number correctly. - val track = (retriever.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER - ) ?: "0/0").split("/")[0].toInt() + val track = ( + retriever.extractMetadata( + MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER + ) ?: "0/0" + ).split("/")[0].toInt() - // Something has gone horribly wrong if a file has no duration. + // Something has gone horribly wrong if a file has no duration, + // so assert it as such. val duration = retriever.extractMetadata( MediaMetadataRetriever.METADATA_KEY_DURATION )!!.toLong() @@ -117,7 +123,7 @@ class MusicRepository { ) } - // Close the retriever when done so that it gets garbage collected + // Close the retriever when done so that it gets garbage collected [I hope] retriever.close() } @@ -127,7 +133,6 @@ class MusicRepository { ) return songList - } catch (error: Exception) { // TODO: Add better error handling