playback: fix crash on state restore
Fix a crash stemming from applying the playback state on the main thread instead of the background thread. all: add misc todos
This commit is contained in:
parent
182883ef2d
commit
736f3ec6b7
5 changed files with 10 additions and 7 deletions
|
@ -51,7 +51,7 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||||
* TODO: Unit testing
|
* TODO: Unit testing
|
||||||
* TODO: Fix UID naming
|
* TODO: Fix UID naming
|
||||||
* TODO: Leverage FlexibleListAdapter more in dialogs (Disable item anims)
|
* TODO: Leverage FlexibleListAdapter more in dialogs (Disable item anims)
|
||||||
* TODO: Try to move on from synchronized and volatile in shared objs
|
* TODO: Improve multi-threading support in shared objects
|
||||||
*/
|
*/
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import android.view.View
|
||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
|
import org.oxycblt.auxio.util.logW
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [RecyclerView.Adapter] that supports indicating the playback status of a particular item.
|
* A [RecyclerView.Adapter] that supports indicating the playback status of a particular item.
|
||||||
|
@ -71,7 +72,7 @@ abstract class PlayingIndicatorAdapter<T, VH : RecyclerView.ViewHolder>(
|
||||||
if (pos > -1) {
|
if (pos > -1) {
|
||||||
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
|
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
|
||||||
} else {
|
} else {
|
||||||
logD("oldItem was not in adapter data")
|
logW("oldItem was not in adapter data")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ abstract class PlayingIndicatorAdapter<T, VH : RecyclerView.ViewHolder>(
|
||||||
if (pos > -1) {
|
if (pos > -1) {
|
||||||
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
|
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
|
||||||
} else {
|
} else {
|
||||||
logD("newItem was not in adapter data")
|
logW("newItem was not in adapter data")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ abstract class PlayingIndicatorAdapter<T, VH : RecyclerView.ViewHolder>(
|
||||||
if (pos > -1) {
|
if (pos > -1) {
|
||||||
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
|
notifyItemChanged(pos, PAYLOAD_PLAYING_INDICATOR_CHANGED)
|
||||||
} else {
|
} else {
|
||||||
logD("newItem was not in adapter data")
|
logW("newItem was not in adapter data")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,7 @@ private class UserLibraryImpl(
|
||||||
override fun findPlaylist(name: String) = playlistMap.values.find { it.name.raw == name }
|
override fun findPlaylist(name: String) = playlistMap.values.find { it.name.raw == name }
|
||||||
|
|
||||||
override suspend fun createPlaylist(name: String, songs: List<Song>) {
|
override suspend fun createPlaylist(name: String, songs: List<Song>) {
|
||||||
|
// TODO: Use synchronized with value access too
|
||||||
val playlistImpl = PlaylistImpl.from(name, songs, musicSettings)
|
val playlistImpl = PlaylistImpl.from(name, songs, musicSettings)
|
||||||
synchronized(this) { playlistMap[playlistImpl.uid] = playlistImpl }
|
synchronized(this) { playlistMap[playlistImpl.uid] = playlistImpl }
|
||||||
val rawPlaylist =
|
val rawPlaylist =
|
||||||
|
|
|
@ -236,13 +236,11 @@ class PlaybackPanelFragment :
|
||||||
requireBinding().playbackShuffle.isActivated = isShuffled
|
requireBinding().playbackShuffle.isActivated = isShuffled
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Navigate to one of the currently playing [Song]'s Artists. */
|
|
||||||
private fun navigateToCurrentArtist() {
|
private fun navigateToCurrentArtist() {
|
||||||
val song = playbackModel.song.value ?: return
|
val song = playbackModel.song.value ?: return
|
||||||
navModel.exploreNavigateToParentArtist(song)
|
navModel.exploreNavigateToParentArtist(song)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Navigate to the currently playing [Song]'s albums. */
|
|
||||||
private fun navigateToCurrentAlbum() {
|
private fun navigateToCurrentAlbum() {
|
||||||
val song = playbackModel.song.value ?: return
|
val song = playbackModel.song.value ?: return
|
||||||
navModel.exploreNavigateTo(song.album)
|
navModel.exploreNavigateTo(song.album)
|
||||||
|
|
|
@ -44,6 +44,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.oxycblt.auxio.BuildConfig
|
import org.oxycblt.auxio.BuildConfig
|
||||||
import org.oxycblt.auxio.music.MusicRepository
|
import org.oxycblt.auxio.music.MusicRepository
|
||||||
import org.oxycblt.auxio.music.MusicSettings
|
import org.oxycblt.auxio.music.MusicSettings
|
||||||
|
@ -355,7 +356,9 @@ class PlaybackService :
|
||||||
logD("Restoring playback state")
|
logD("Restoring playback state")
|
||||||
restoreScope.launch {
|
restoreScope.launch {
|
||||||
persistenceRepository.readState()?.let {
|
persistenceRepository.readState()?.let {
|
||||||
playbackManager.applySavedState(it, false)
|
// Apply the saved state on the main thread to prevent code expecting
|
||||||
|
// state updates on the main thread from crashing.
|
||||||
|
withContext(Dispatchers.Main) { playbackManager.applySavedState(it, false) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue