Как исправить это предупреждение «GlobalScope. Это деликатный API, и его использование требует осторожности»?Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Как исправить это предупреждение «GlobalScope. Это деликатный API, и его использование требует осторожности»?

Сообщение Anonymous »

Сейчас я учусь создавать музыкальное приложение с помощью Compose и Media3. onIsPlayingChanged(isPlaying: Boolean) в этом методе я использую GlobalScope, студия Android дала мне это предупреждение: «Это деликатный API, и его использование требует осторожности. Убедитесь, что вы полностью прочитали и поняли документацию объявления, помеченного как деликатный. API."
Я пытался использовать другую переменную задания, но не знаю, как это сделать. Как исправить код, чтобы он соответствовал рекомендациям Google по разработке Android.
это код MusicServiceHandler

Код: Выделить всё

import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.exoplayer.ExoPlayer
import com.techullurgy.media3musicplayer.utils.MediaStateEvents
import com.techullurgy.media3musicplayer.utils.MusicStates
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class MusicServiceHandler(
private val exoPlayer: Player,
) : Player.Listener {

private val _musicStates: MutableStateFlow = MutableStateFlow(MusicStates.Initial)
val musicStates: StateFlow = _musicStates.asStateFlow()

private var job: Job? = null

init {
exoPlayer.addListener(this)
}

fun setMediaItem(mediaItem: MediaItem) {
exoPlayer.setMediaItem(mediaItem)
exoPlayer.prepare()
}

fun setMediaItemList(mediaItems: List) {
exoPlayer.setMediaItems(mediaItems)
exoPlayer.prepare()
}

suspend fun onMediaStateEvents(
mediaStateEvents: MediaStateEvents,
selectedMusicIndex: Int = -1,
seekPosition: Long = 0,
) {
when (mediaStateEvents) {
MediaStateEvents.Backward -> exoPlayer.seekBack()
MediaStateEvents.Forward -> exoPlayer.seekForward()
MediaStateEvents.PlayPause -> playPauseMusic()
MediaStateEvents.SeekTo -> exoPlayer.seekTo(seekPosition)
MediaStateEvents.SeekToNext -> exoPlayer.seekToNext()
MediaStateEvents.SeekToPrevious -> exoPlayer.seekToPrevious()
MediaStateEvents.Stop -> stopProgressUpdate()
MediaStateEvents.SelectedMusicChange -> {
when (selectedMusicIndex) {
exoPlayer.currentMediaItemIndex -> {
playPauseMusic()
}

else -> {
exoPlayer.seekToDefaultPosition(selectedMusicIndex)
_musicStates.value = MusicStates.MediaPlaying(
isPlaying = true
)
exoPlayer.playWhenReady = true
startProgressUpdate()
}
}
}

is MediaStateEvents.MediaProgress -> {
exoPlayer.seekTo(
(exoPlayer.duration * mediaStateEvents.progress).toLong()
)
}
}
}

override fun onPlaybackStateChanged(playbackState: Int) {
when (playbackState) {
ExoPlayer.STATE_BUFFERING -> _musicStates.value =
MusicStates.MediaBuffering(exoPlayer.currentPosition)

ExoPlayer.STATE_READY -> _musicStates.value = MusicStates.MediaReady(exoPlayer.duration)

Player.STATE_ENDED -> {
// no-op
}

Player.STATE_IDLE ->  {
// no-op
}
}
}

@OptIn(DelicateCoroutinesApi::class)
override fun onIsPlayingChanged(isPlaying: Boolean) {
_musicStates.value = MusicStates.MediaPlaying(isPlaying = isPlaying)
_musicStates.value = MusicStates.CurrentMediaPlaying(exoPlayer.currentMediaItemIndex)
if (isPlaying) {
GlobalScope.launch(Dispatchers.Main) {
startProgressUpdate()
}
} else {
stopProgressUpdate()
}
}

private suspend fun playPauseMusic() {
if (exoPlayer.isPlaying) {
exoPlayer.pause()
stopProgressUpdate()
} else {
exoPlayer.play()
_musicStates.value = MusicStates.MediaPlaying(
isPlaying = true
)
startProgressUpdate()
}
}

private suspend fun startProgressUpdate() = job.run {
while (true) {
delay(500)
_musicStates.value = MusicStates.MediaProgress(exoPlayer.currentPosition)
}
}

private fun stopProgressUpdate() {
job?.cancel()
_musicStates.value = MusicStates.MediaPlaying(isPlaying = false)
}
}
эта модель MusicView

Код: Выделить всё

@OptIn(SavedStateHandleSaveableApi::class)
class MusicViewModel(
savedStateHandle: SavedStateHandle,
) : ViewModel(), KoinComponent {

private val musicServiceHandler: MusicServiceHandler by inject()
private val repository: MusicRepository by inject()

private var duration by savedStateHandle.saveable { mutableLongStateOf(0L) }
var progress by savedStateHandle.saveable { mutableFloatStateOf(0f) }
private var progressValue by savedStateHandle.saveable { mutableStateOf("00:00") }
var isMusicPlaying by savedStateHandle.saveable { mutableStateOf(false) }
var currentSelectedMusic by mutableStateOf(
AudioItem(
0L,
"".toUri(),
"",
"",
0,
"",
"",
null
)
)

var musicList by mutableStateOf(listOf())

private val _homeUiState: MutableStateFlow =
MutableStateFlow(HomeUIState.InitialHome)
val homeUIState: StateFlow = _homeUiState.asStateFlow()

init {
getMusicData()
}

init {
viewModelScope.launch {
musicServiceHandler.musicStates.collectLatest { musicStates: MusicStates ->
when (musicStates) {
MusicStates.Initial -> _homeUiState.value = HomeUIState.InitialHome
is MusicStates.MediaBuffering -> progressCalculation(musicStates.progress)
is MusicStates.MediaPlaying -> isMusicPlaying = musicStates.isPlaying
is MusicStates.MediaProgress -> progressCalculation(musicStates.progress)
is MusicStates.CurrentMediaPlaying -> {
currentSelectedMusic = musicList[musicStates.mediaItemIndex]
}

is MusicStates.MediaReady -> {
duration = musicStates.duration
_homeUiState.value = HomeUIState.HomeReady
}
}
}
}
}

fun onHomeUiEvents(homeUiEvents: HomeUiEvents) = viewModelScope.launch {
when (homeUiEvents) {
HomeUiEvents.Backward -> musicServiceHandler.onMediaStateEvents(MediaStateEvents.Backward)
HomeUiEvents.Forward -> musicServiceHandler.onMediaStateEvents(MediaStateEvents.Forward)
HomeUiEvents.SeekToNext -> musicServiceHandler.onMediaStateEvents(MediaStateEvents.SeekToNext)
HomeUiEvents.SeekToPrevious -> musicServiceHandler.onMediaStateEvents(MediaStateEvents.SeekToPrevious)
is HomeUiEvents.PlayPause -> {
musicServiceHandler.onMediaStateEvents(
MediaStateEvents.PlayPause
)
}

is HomeUiEvents.SeekTo -> {
musicServiceHandler.onMediaStateEvents(
MediaStateEvents.SeekTo,
seekPosition = ((duration * homeUiEvents.position) / 100f).toLong()
)
}

is HomeUiEvents.CurrentAudioChanged ->  {
musicServiceHandler.onMediaStateEvents(
MediaStateEvents.SelectedMusicChange,
selectedMusicIndex = homeUiEvents.index
)
}

is HomeUiEvents.UpdateProgress -> {
musicServiceHandler.onMediaStateEvents(
MediaStateEvents.MediaProgress(
homeUiEvents.progress
)
)
progress = homeUiEvents.progress
}

}
}

private fun getMusicData() {
viewModelScope.launch {
val musicData = repository.getAudioData()
musicList = musicData
setMusicItems()
}
}

private fun setMusicItems() {
musicList.map { audioItem ->
MediaItem.Builder()
.setUri(audioItem.uri)
.setMediaMetadata(
MediaMetadata.Builder()
.setAlbumArtist(audioItem.artist)
.setDisplayTitle(audioItem.title)
.setSubtitle(audioItem.displayName)
.build()
)
.build()
}.also {
musicServiceHandler.setMediaItemList(it)
}
}

private fun progressCalculation(currentProgress: Long) {
progress =
if (currentProgress > 0) ((currentProgress.toFloat() / duration.toFloat()) * 100f)
else 0f

progressValue = formatDurationValue(currentProgress)
}

private fun formatDurationValue(duration: Long): String {
val minutes = MINUTES.convert(duration, MILLISECONDS)
val seconds = (minutes) - minutes * SECONDS.convert(1, MINUTES)

return String.format("%02d:%02d", minutes, seconds)
}

override fun onCleared() {
viewModelScope.launch {
musicServiceHandler.onMediaStateEvents(MediaStateEvents.Stop)
}
super.onCleared()
}
}

Подробнее здесь: https://stackoverflow.com/questions/787 ... se-require
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»