Update music loading init process

Change the loading process so that LoadingViewModel no longer requires an application instance to start. Also move the main music loading code to an internal function.
This commit is contained in:
OxygenCobalt 2021-03-05 13:45:43 -07:00
parent 2c93e3f362
commit 466629e43d
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
7 changed files with 43 additions and 54 deletions

View file

@ -20,9 +20,7 @@ import org.oxycblt.auxio.music.MusicStore
* @author OxygenCobalt
*/
class LoadingFragment : Fragment() {
private val loadingModel: LoadingViewModel by viewModels {
LoadingViewModel.Factory(requireActivity().application)
}
private val loadingModel: LoadingViewModel by viewModels()
override fun onCreateView(
inflater: LayoutInflater,
@ -71,7 +69,7 @@ class LoadingFragment : Fragment() {
}
if (loadingModel.response.value == null) {
loadingModel.load()
loadingModel.load(requireContext())
}
return binding.root
@ -110,7 +108,7 @@ class LoadingFragment : Fragment() {
if (granted) {
// If granted, its now safe to load, which will clear the NO_PERMS response
// we applied earlier.
loadingModel.load()
loadingModel.load(requireContext())
}
}

View file

@ -1,10 +1,9 @@
package org.oxycblt.auxio.loading
import android.app.Application
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
import org.oxycblt.auxio.music.MusicStore
@ -13,7 +12,7 @@ import org.oxycblt.auxio.music.MusicStore
* ViewModel responsible for the loading UI and beginning the loading process overall.
* @author OxygenCobalt
*/
class LoadingViewModel(private val app: Application) : ViewModel() {
class LoadingViewModel : ViewModel() {
private val mResponse = MutableLiveData<MusicStore.Response?>(null)
private val mDoGrant = MutableLiveData(false)
@ -27,9 +26,9 @@ class LoadingViewModel(private val app: Application) : ViewModel() {
private val musicStore = MusicStore.getInstance()
/**
* Begin the music loading process. The response is pushed to [response]
* Begin the music loading process. The response from MusicStore is pushed to [response]
*/
fun load() {
fun load(context: Context) {
// Dont start a new load if the last one hasnt finished
if (isBusy) return
@ -37,7 +36,7 @@ class LoadingViewModel(private val app: Application) : ViewModel() {
mResponse.value = null
viewModelScope.launch {
mResponse.value = musicStore.load(app)
mResponse.value = musicStore.load(context)
isBusy = false
}
}
@ -62,15 +61,4 @@ class LoadingViewModel(private val app: Application) : ViewModel() {
fun notifyNoPermissions() {
mResponse.value = MusicStore.Response.NO_PERMS
}
@Suppress("UNCHECKED_CAST")
class Factory(private val application: Application) : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(LoadingViewModel::class.java)) {
return LoadingViewModel(application) as T
}
throw IllegalArgumentException("Unknown ViewModel class.")
}
}
}

View file

@ -1,7 +1,7 @@
package org.oxycblt.auxio.music
import android.app.Application
import android.content.ContentResolver
import android.content.Context
import android.net.Uri
import android.provider.OpenableColumns
import kotlinx.coroutines.Dispatchers
@ -42,42 +42,45 @@ class MusicStore private constructor() {
/**
* Load/Sort the entire music library. Should always be ran on a coroutine.
* @param app [Application] required to load the music.
*/
suspend fun load(app: Application): Response {
suspend fun load(context: Context): Response {
return withContext(Dispatchers.IO) {
// TODO: Move this to an internal function
this@MusicStore.logD("Starting initial music load...")
loadMusicInternal(context)
}
}
/**
* Do the internal music loading process.
*/
private fun loadMusicInternal(context: Context): Response {
logD("Starting initial music load...")
try {
val start = System.currentTimeMillis()
try {
val loader = MusicLoader(app)
loader.load()
val loader = MusicLoader(context)
loader.load()
if (loader.songs.isEmpty()) {
return@withContext Response.NO_MUSIC
}
mSongs = loader.songs
mAlbums = loader.albums
mArtists = loader.artists
mGenres = loader.genres
this@MusicStore.logD(
"Music load completed successfully in ${System.currentTimeMillis() - start}ms."
)
} catch (e: Exception) {
logE("Something went horribly wrong.")
logE(e.stackTraceToString())
return@withContext Response.FAILED
if (loader.songs.isEmpty()) {
return Response.NO_MUSIC
}
loaded = true
mSongs = loader.songs
mAlbums = loader.albums
mArtists = loader.artists
mGenres = loader.genres
return@withContext Response.SUCCESS
logD("Music load completed successfully in ${System.currentTimeMillis() - start}ms.")
} catch (e: Exception) {
logE("Something went horribly wrong.")
logE(e.stackTraceToString())
return Response.FAILED
}
loaded = true
return Response.SUCCESS
}
/**

View file

@ -12,8 +12,8 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.ui.getPlural
/**
* List of ID3 genres + Winamp extensions, each index corresponds to their int value.
* There are a lot more int-genre extensions as far as Im aware, but this works for most cases.
* A complete array of all the hardcoded genre values for ID3 <v3, contains standard genres and
* winamp extensions.
*/
private val ID3_GENRES = arrayOf(
// ID3 Standard

View file

@ -172,6 +172,8 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback {
if (playbackManager.isRestored && musicStore.loaded) {
playWithUriInternal(uri, context)
} else {
logD("Cant play this URI right now, waiting...")
mIntentUri = uri
}
}

View file

@ -247,8 +247,6 @@ class PlaybackService : Service(), Player.EventListener, PlaybackStateManager.Ca
notification.setPlaying(this, isPlaying)
startForegroundOrNotify()
logD("Playing Status: $isPlaying")
}
override fun onLoopUpdate(loopMode: LoopMode) {

View file

@ -53,7 +53,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/inter_semibold"
android:onClick="@{() -> loadingModel.load()}"
android:onClick="@{() -> loadingModel.load(context)}"
android:text="@string/label_retry"
android:textColor="?attr/colorPrimary"
android:visibility="gone"