diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetController.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetController.kt index 97610465f..14f017e4d 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetController.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetController.kt @@ -8,7 +8,9 @@ import org.oxycblt.auxio.settings.SettingsManager /** * A wrapper around each [WidgetProvider] that plugs into the main Auxio process and updates the - * widget state based off of that. This cannot be rolled into [WidgetProvider] directly. + * widget state based off of that. This cannot be rolled into [WidgetProvider] directly, as it may + * result in memory leaks if [PlaybackStateManager]/[SettingsManager] gets created and bound + * to without being released. */ class WidgetController(private val context: Context) : PlaybackStateManager.Callback, @@ -22,6 +24,9 @@ class WidgetController(private val context: Context) : settingsManager.addCallback(this) } + /* + * Update the widget. + */ fun update() { widget.update(context, playbackManager) } diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetState.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetState.kt index 392504ed3..7f89fae25 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetState.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetState.kt @@ -5,8 +5,8 @@ import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.state.LoopMode /* - * A condensed variant of the current playback state, used so that PlaybackStateManager does not - * need to be queried directly. + * An immutable condensed variant of the current playback state, used so that PlaybackStateManager + * does not need to be queried directly. */ data class WidgetState( val song: Song, diff --git a/info/ARCHITECTURE.md b/info/ARCHITECTURE.md index c41198255..b998c30dc 100644 --- a/info/ARCHITECTURE.md +++ b/info/ARCHITECTURE.md @@ -166,7 +166,7 @@ PlaybackStateManager───────────────────┘ `PlaybackStateManager` is the shared object that contains the master copy of the playback state, doing all operations on it. This object should ***NEVER*** be used in a UI, as it does not sanitize input and can cause major problems if a Volatile UI interacts with it. It's callback system is also prone to memory leaks if not cleared when done. `PlaybackViewModel` should be used instead, as it exposes stable data and safe functions that UIs can use to interact with the playback state. -`PlaybackService`'s job is to use the playback state to manage the ExoPlayer instance and notification and also modify the state depending on system events, such as when a button is pressed on a headset. It should **never** be bound to, mostly because there is no need given that `PlaybackViewModel` exposes the same data in a much safer fashion. `PlaybackService` also controls the `PlaybackSessionConnector` and `AudioReactor` classes, which manage the `MediaSession` and `AudioFocus` state respectively. +`PlaybackService`'s job is to use the playback state to manage the ExoPlayer instance, the notification, and also modify the state depending on system events, such as when a button is pressed on a headset. It should **never** be bound to, mostly because there is no need given that `PlaybackViewModel` exposes the same data in a much safer fashion. `PlaybackService` also controls the `PlaybackSessionConnector`, `AudioReactor`, and `WidgetController` classes, which manage the `MediaSession`, Audio Focus, and Widgets respectively. #### `.recycler` @@ -189,4 +189,31 @@ Package for the songs UI, there is no data management here, only a user interfac Shared User Interface utilities. This is primarily made up of convenience/extension functions relating to Views, Resources, Configurations, and Contexts. It also contains some dedicated utilities, such as: - The Accent Management system - `newMenu` and `ActionMenu`, which automates menu creation for most data types -- `memberBinding` and `MemberBinder`, which allows for ViewBindings to be used as a member variable without memory leaks or nullability issues. \ No newline at end of file +- `memberBinding` and `MemberBinder`, which allows for ViewBindings to be used as a member variable without memory leaks or nullability issues. + +#### `.widgets` + +The widget sub-module. This module differs heavily from the rest of Auxio, as widget UIs can't be controlled in the same +way that UIs in the main process can. + +Widgets are controlled by two pieces of code: + +- `WidgetProvider`, which provides the widget layouts to the system +- `WidgetController`, which acts as an intermediary between the Auxio process and the widget [ex. Monitoring the playback state] + +The widget update process is described in this diagram: + +``` +WidgetController<──────────PlaybackService + │ Controls ^ + │ │ + │ Updates │ + │ │ + │ │ + v Requests Update │ + WidgetProvider───────────────────┘ +``` + +When `WidgetProvider` creates a layout, it first turns the `PlaybackStateManager` instance into a `WidgetState`, which is +an immutable version of the playback state that negates some of the problems with using a shared object here. It then picks +a layout [e.g "Form"] depending on its current dimensions and applies the `WidgetState` object to that. \ No newline at end of file