Move MusicRepository initialization to coroutine
Move the init call to MusicRepostiory to a coroutine so that it doesnt stop the UI thread.
This commit is contained in:
parent
21a110edb0
commit
3134e313a3
3 changed files with 55 additions and 17 deletions
|
@ -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.")
|
||||
|
||||
|
|
|
@ -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 <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||
if (modelClass.isAssignableFrom(LibraryViewModel::class.java)) {
|
||||
return LibraryViewModel(application) as T
|
||||
}
|
||||
throw IllegalArgumentException("Unknown ViewModel class")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -84,17 +85,22 @@ class MusicRepository {
|
|||
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
|
||||
|
||||
|
|
Loading…
Reference in a new issue