Tidied up usage of GlobalScope to the profit of AndroidX's lifecycle coroutine scopes.

This commit is contained in:
Antoine POPINEAU 2020-06-25 01:26:15 +02:00
parent eb57b4c872
commit 9c61fcf462
No known key found for this signature in database
GPG Key ID: A78AC64694F84063
25 changed files with 117 additions and 151 deletions

View File

@ -103,6 +103,7 @@ dependencies {
implementation("androidx.appcompat:appcompat:1.1.0") implementation("androidx.appcompat:appcompat:1.1.0")
implementation("androidx.core:core-ktx:1.5.0-alpha01") implementation("androidx.core:core-ktx:1.5.0-alpha01")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.0-alpha05")
implementation("androidx.coordinatorlayout:coordinatorlayout:1.1.0") implementation("androidx.coordinatorlayout:coordinatorlayout:1.1.0")
implementation("androidx.preference:preference:1.1.1") implementation("androidx.preference:preference:1.1.1")
implementation("androidx.recyclerview:recyclerview:1.1.0") implementation("androidx.recyclerview:recyclerview:1.1.0")

View File

@ -17,10 +17,6 @@
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"> android:usesCleartextTraffic="true">
<!-- <meta-data
android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
android:value="com.google.android.exoplayer2.ext.cast.DefaultCastOptionsProvider"/> -->
<activity <activity
android:name="com.github.apognu.otter.activities.SplashActivity" android:name="com.github.apognu.otter.activities.SplashActivity"
android:launchMode="singleInstance" android:launchMode="singleInstance"

View File

@ -1,19 +1,21 @@
package com.github.apognu.otter.activities package com.github.apognu.otter.activities
import android.os.Bundle import android.os.Bundle
import kotlinx.coroutines.flow.collect
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.apognu.otter.Otter import com.github.apognu.otter.Otter
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.DownloadsAdapter import com.github.apognu.otter.adapters.DownloadsAdapter
import com.github.apognu.otter.utils.* import com.github.apognu.otter.utils.Event
import com.github.apognu.otter.utils.EventBus
import com.github.apognu.otter.utils.getMetadata
import com.google.android.exoplayer2.offline.Download import com.google.android.exoplayer2.offline.Download
import kotlinx.android.synthetic.main.activity_downloads.* import kotlinx.android.synthetic.main.activity_downloads.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Default
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -34,7 +36,7 @@ class DownloadsActivity : AppCompatActivity() {
downloads.adapter = it downloads.adapter = it
} }
GlobalScope.launch(IO) { lifecycleScope.launch(Default) {
while (true) { while (true) {
delay(1000) delay(1000)
refreshProgress() refreshProgress()
@ -45,7 +47,7 @@ class DownloadsActivity : AppCompatActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
GlobalScope.launch(IO) { lifecycleScope.launch(Default) {
EventBus.get().collect { event -> EventBus.get().collect { event ->
if (event is Event.DownloadChanged) { if (event is Event.DownloadChanged) {
refreshTrack(event.download) refreshTrack(event.download)
@ -57,7 +59,7 @@ class DownloadsActivity : AppCompatActivity() {
} }
private fun refresh() { private fun refresh() {
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
val cursor = Otter.get().exoDownloadManager.downloadIndex.getDownloads() val cursor = Otter.get().exoDownloadManager.downloadIndex.getDownloads()
adapter.downloads.clear() adapter.downloads.clear()

View File

@ -5,6 +5,7 @@ import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.fragments.LoginDialog import com.github.apognu.otter.fragments.LoginDialog
import com.github.apognu.otter.utils.AppContext import com.github.apognu.otter.utils.AppContext
@ -17,7 +18,6 @@ import com.google.gson.Gson
import com.preference.PowerPreference import com.preference.PowerPreference
import kotlinx.android.synthetic.main.activity_login.* import kotlinx.android.synthetic.main.activity_login.*
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
data class FwCredentials(val token: String, val non_field_errors: List<String>?) data class FwCredentials(val token: String, val non_field_errors: List<String>?)
@ -89,7 +89,7 @@ class LoginActivity : AppCompatActivity() {
show(supportFragmentManager, "LoginDialog") show(supportFragmentManager, "LoginDialog")
} }
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
try { try {
val (_, response, result) = Fuel.post("$hostname/api/v1/token/", body) val (_, response, result) = Fuel.post("$hostname/api/v1/token/", body)
.awaitObjectResponseResult(gsonDeserializerOf(FwCredentials::class.java)) .awaitObjectResponseResult(gsonDeserializerOf(FwCredentials::class.java))
@ -146,7 +146,7 @@ class LoginActivity : AppCompatActivity() {
show(supportFragmentManager, "LoginDialog") show(supportFragmentManager, "LoginDialog")
} }
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
try { try {
val (_, _, result) = Fuel.get("$hostname/api/v1/tracks/") val (_, _, result) = Fuel.get("$hostname/api/v1/tracks/")
.awaitObjectResponseResult(gsonDeserializerOf(FwCredentials::class.java)) .awaitObjectResponseResult(gsonDeserializerOf(FwCredentials::class.java))

View File

@ -5,7 +5,6 @@ import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.graphics.Bitmap import android.graphics.Bitmap
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics import android.util.DisplayMetrics
@ -19,6 +18,7 @@ import androidx.core.graphics.drawable.toDrawable
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.lifecycle.lifecycleScope
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.fragments.* import com.github.apognu.otter.fragments.*
import com.github.apognu.otter.playback.MediaControlsManager import com.github.apognu.otter.playback.MediaControlsManager
@ -38,11 +38,9 @@ import com.squareup.picasso.Picasso
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.partial_now_playing.* import kotlinx.android.synthetic.main.partial_now_playing.*
import kotlinx.android.synthetic.main.row_download.* import kotlinx.coroutines.Dispatchers.Default
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -55,10 +53,6 @@ class MainActivity : AppCompatActivity() {
private val favoriteRepository = FavoritesRepository(this) private val favoriteRepository = FavoritesRepository(this)
private val favoriteCheckRepository = FavoritedRepository(this) private val favoriteCheckRepository = FavoritedRepository(this)
private var eventBus: Job? = null
private var commandBus: Job? = null
private var progressBus: Job? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -76,22 +70,18 @@ class MainActivity : AppCompatActivity() {
.replace(R.id.container, BrowseFragment()) .replace(R.id.container, BrowseFragment())
.commit() .commit()
CommandBus.send(Command.RefreshService) watchEventBus()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (eventBus == null) {
watchEventBus()
}
CommandBus.send(Command.RefreshService)
startService(Intent(this, PlayerService::class.java)) startService(Intent(this, PlayerService::class.java))
DownloadService.start(this, PinService::class.java) DownloadService.start(this, PinService::class.java)
GlobalScope.launch(IO) { CommandBus.send(Command.RefreshService)
lifecycleScope.launch(IO) {
Userinfo.get() Userinfo.get()
} }
@ -132,19 +122,6 @@ class MainActivity : AppCompatActivity() {
} }
} }
override fun onPause() {
super.onPause()
eventBus?.cancel()
eventBus = null
commandBus?.cancel()
commandBus = null
progressBus?.cancel()
progressBus = null
}
override fun onBackPressed() { override fun onBackPressed() {
if (now_playing.isOpened()) { if (now_playing.isOpened()) {
now_playing.close() now_playing.close()
@ -157,8 +134,6 @@ class MainActivity : AppCompatActivity() {
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.toolbar, menu) menuInflater.inflate(R.menu.toolbar, menu)
// CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.cast)
menu?.findItem(R.id.nav_only_my_music)?.isChecked = Settings.getScope() == "me" menu?.findItem(R.id.nav_only_my_music)?.isChecked = Settings.getScope() == "me"
return true return true
@ -210,10 +185,6 @@ class MainActivity : AppCompatActivity() {
} }
} }
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
}
private fun launchFragment(fragment: Fragment) { private fun launchFragment(fragment: Fragment) {
supportFragmentManager.fragments.lastOrNull()?.also { oldFragment -> supportFragmentManager.fragments.lastOrNull()?.also { oldFragment ->
oldFragment.enterTransition = null oldFragment.enterTransition = null
@ -237,7 +208,7 @@ class MainActivity : AppCompatActivity() {
@SuppressLint("NewApi") @SuppressLint("NewApi")
private fun watchEventBus() { private fun watchEventBus() {
eventBus = GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
EventBus.get().collect { message -> EventBus.get().collect { message ->
when (message) { when (message) {
is Event.LogOut -> { is Event.LogOut -> {
@ -312,7 +283,7 @@ class MainActivity : AppCompatActivity() {
} }
} }
commandBus = GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
CommandBus.get().collect { command -> CommandBus.get().collect { command ->
when (command) { when (command) {
is Command.RefreshTrack -> refreshCurrentTrack(command.track) is Command.RefreshTrack -> refreshCurrentTrack(command.track)
@ -320,7 +291,7 @@ class MainActivity : AppCompatActivity() {
} }
} }
progressBus = GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
ProgressBus.get().collect { (current, duration, percent) -> ProgressBus.get().collect { (current, duration, percent) ->
now_playing_progress.progress = percent now_playing_progress.progress = percent
now_playing_details_progress.progress = percent now_playing_details_progress.progress = percent
@ -384,7 +355,7 @@ class MainActivity : AppCompatActivity() {
} }
if (now_playing_details_cover == null) { if (now_playing_details_cover == null) {
GlobalScope.launch(IO) { lifecycleScope.launch(Default) {
val width = DisplayMetrics().apply { val width = DisplayMetrics().apply {
windowManager.defaultDisplay.getMetrics(this) windowManager.defaultDisplay.getMetrics(this)
}.widthPixels }.widthPixels
@ -437,8 +408,8 @@ class MainActivity : AppCompatActivity() {
} }
now_playing_details_favorite?.let { now_playing_details_favorite -> now_playing_details_favorite?.let { now_playing_details_favorite ->
favoriteCheckRepository.fetch().untilNetwork(IO) { favorites, _, _ -> favoriteCheckRepository.fetch().untilNetwork(lifecycleScope, IO) { favorites, _, _ ->
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
track.favorite = favorites.contains(track.id) track.favorite = favorites.contains(track.id)
when (track.favorite) { when (track.favorite) {
@ -507,7 +478,7 @@ class MainActivity : AppCompatActivity() {
private fun incrementListenCount(track: Track?) { private fun incrementListenCount(track: Track?) {
track?.let { track?.let {
GlobalScope.launch(IO) { lifecycleScope.launch(IO) {
try { try {
Fuel Fuel
.post(mustNormalizeUrl("/api/v1/history/listenings/")) .post(mustNormalizeUrl("/api/v1/history/listenings/"))

View File

@ -3,6 +3,7 @@ package com.github.apognu.otter.activities
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.SearchAdapter import com.github.apognu.otter.adapters.SearchAdapter
@ -66,21 +67,21 @@ class SearchActivity : AppCompatActivity() {
adapter.tracks.clear() adapter.tracks.clear()
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
artistsRepository.fetch(Repository.Origin.Network.origin).untilNetwork { artists, _, _ -> artistsRepository.fetch(Repository.Origin.Network.origin).untilNetwork(lifecycleScope) { artists, _, _ ->
done++ done++
adapter.artists.addAll(artists) adapter.artists.addAll(artists)
refresh() refresh()
} }
albumsRepository.fetch(Repository.Origin.Network.origin).untilNetwork { albums, _, _ -> albumsRepository.fetch(Repository.Origin.Network.origin).untilNetwork(lifecycleScope) { albums, _, _ ->
done++ done++
adapter.albums.addAll(albums) adapter.albums.addAll(albums)
refresh() refresh()
} }
tracksRepository.fetch(Repository.Origin.Network.origin).untilNetwork { tracks, _, _ -> tracksRepository.fetch(Repository.Origin.Network.origin).untilNetwork(lifecycleScope) { tracks, _, _ ->
done++ done++
adapter.tracks.addAll(tracks) adapter.tracks.addAll(tracks)

View File

@ -7,17 +7,20 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.fragments.FunkwhaleAdapter import com.github.apognu.otter.fragments.FunkwhaleAdapter
import com.github.apognu.otter.utils.* import com.github.apognu.otter.utils.AppContext
import com.github.apognu.otter.utils.Event
import com.github.apognu.otter.utils.EventBus
import com.github.apognu.otter.utils.Radio
import com.github.apognu.otter.views.LoadingImageView import com.github.apognu.otter.views.LoadingImageView
import com.preference.PowerPreference import com.preference.PowerPreference
import kotlinx.android.synthetic.main.row_radio.view.* import kotlinx.android.synthetic.main.row_radio.view.*
import kotlinx.android.synthetic.main.row_radio_header.view.* import kotlinx.android.synthetic.main.row_radio_header.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class RadiosAdapter(val context: Context?, private val listener: OnRadioClickListener) : FunkwhaleAdapter<Radio, RadiosAdapter.ViewHolder>() { class RadiosAdapter(val context: Context?, val scope: CoroutineScope, private val listener: OnRadioClickListener) : FunkwhaleAdapter<Radio, RadiosAdapter.ViewHolder>() {
interface OnRadioClickListener { interface OnRadioClickListener {
fun onClick(holder: ViewHolder, radio: Radio) fun onClick(holder: ViewHolder, radio: Radio)
} }
@ -139,7 +142,7 @@ class RadiosAdapter(val context: Context?, private val listener: OnRadioClickLis
art.setColorFilter(context.getColor(R.color.controlForeground)) art.setColorFilter(context.getColor(R.color.controlForeground))
GlobalScope.launch(Main) { scope.launch(Main) {
EventBus.get().collect { message -> EventBus.get().collect { message ->
when (message) { when (message) {
is Event.RadioStarted -> { is Event.RadioStarted -> {

View File

@ -8,6 +8,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.CircularProgressDrawable import androidx.swiperefreshlayout.widget.CircularProgressDrawable
import androidx.transition.Fade import androidx.transition.Fade
@ -24,7 +25,6 @@ import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.android.synthetic.main.fragment_albums.* import kotlinx.android.synthetic.main.fragment_albums.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -126,7 +126,7 @@ class AlbumsFragment : FunkwhaleFragment<Album, AlbumsAdapter>() {
play.icon = loader play.icon = loader
play.isClickable = false play.isClickable = false
GlobalScope.launch(IO) { lifecycleScope.launch(IO) {
artistTracksRepository.fetch(Repository.Origin.Network.origin) artistTracksRepository.fetch(Repository.Origin.Network.origin)
.map { it.data } .map { it.data }
.toList() .toList()

View File

@ -1,6 +1,7 @@
package com.github.apognu.otter.fragments package com.github.apognu.otter.fragments
import android.os.Bundle import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.FavoritesAdapter import com.github.apognu.otter.adapters.FavoritesAdapter
@ -11,7 +12,6 @@ import com.google.android.exoplayer2.offline.Download
import kotlinx.android.synthetic.main.fragment_favorites.* import kotlinx.android.synthetic.main.fragment_favorites.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -32,7 +32,7 @@ class FavoritesFragment : FunkwhaleFragment<Track, FavoritesAdapter>() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
GlobalScope.launch(IO) { lifecycleScope.launch(IO) {
RequestBus.send(Request.GetCurrentTrack).wait<Response.CurrentTrack>()?.let { response -> RequestBus.send(Request.GetCurrentTrack).wait<Response.CurrentTrack>()?.let { response ->
withContext(Main) { withContext(Main) {
adapter.currentTrack = response.track adapter.currentTrack = response.track
@ -49,7 +49,7 @@ class FavoritesFragment : FunkwhaleFragment<Track, FavoritesAdapter>() {
} }
private fun watchEventBus() { private fun watchEventBus() {
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
EventBus.get().collect { message -> EventBus.get().collect { message ->
when (message) { when (message) {
is Event.DownloadChanged -> refreshDownloadedTrack(message.download) is Event.DownloadChanged -> refreshDownloadedTrack(message.download)
@ -57,7 +57,7 @@ class FavoritesFragment : FunkwhaleFragment<Track, FavoritesAdapter>() {
} }
} }
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
CommandBus.get().collect { command -> CommandBus.get().collect { command ->
when (command) { when (command) {
is Command.RefreshTrack -> refreshCurrentTrack(command.track) is Command.RefreshTrack -> refreshCurrentTrack(command.track)

View File

@ -5,16 +5,19 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.apognu.otter.repositories.HttpUpstream import com.github.apognu.otter.repositories.HttpUpstream
import com.github.apognu.otter.repositories.Repository import com.github.apognu.otter.repositories.Repository
import com.github.apognu.otter.utils.* import com.github.apognu.otter.utils.Cache
import com.github.apognu.otter.utils.Event
import com.github.apognu.otter.utils.EventBus
import com.github.apognu.otter.utils.untilNetwork
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.android.synthetic.main.fragment_artists.* import kotlinx.android.synthetic.main.fragment_artists.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -70,7 +73,7 @@ abstract class FunkwhaleFragment<D : Any, A : FunkwhaleAdapter<D, *>> : Fragment
} }
if (listener == null) { if (listener == null) {
listener = GlobalScope.launch(IO) { listener = lifecycleScope.launch(IO) {
EventBus.get().collect { event -> EventBus.get().collect { event ->
if (event is Event.ListingsChanged) { if (event is Event.ListingsChanged) {
withContext(Main) { withContext(Main) {
@ -92,8 +95,8 @@ abstract class FunkwhaleFragment<D : Any, A : FunkwhaleAdapter<D, *>> : Fragment
swiper?.isRefreshing = true swiper?.isRefreshing = true
} }
repository.fetch(upstreams, size).untilNetwork(IO) { data, isCache, hasMore -> repository.fetch(upstreams, size).untilNetwork(lifecycleScope, IO) { data, isCache, hasMore ->
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
if (isCache) { if (isCache) {
adapter.data = data.toMutableList() adapter.data = data.toMutableList()
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
@ -112,7 +115,7 @@ abstract class FunkwhaleFragment<D : Any, A : FunkwhaleAdapter<D, *>> : Fragment
if (!hasMore) { if (!hasMore) {
swiper?.isRefreshing = false swiper?.isRefreshing = false
GlobalScope.launch(IO) { withContext(IO) {
if (adapter.data.isNotEmpty()) { if (adapter.data.isNotEmpty()) {
try { try {
repository.cacheId?.let { cacheId -> repository.cacheId?.let { cacheId ->

View File

@ -5,6 +5,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.TracksAdapter import com.github.apognu.otter.adapters.TracksAdapter
@ -12,7 +13,6 @@ import com.github.apognu.otter.utils.*
import kotlinx.android.synthetic.main.partial_queue.* import kotlinx.android.synthetic.main.partial_queue.*
import kotlinx.android.synthetic.main.partial_queue.view.* import kotlinx.android.synthetic.main.partial_queue.view.*
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -44,7 +44,7 @@ class LandscapeQueueFragment : Fragment() {
} }
private fun refresh() { private fun refresh() {
GlobalScope.launch(Main) { activity?.lifecycleScope?.launch(Main) {
RequestBus.send(Request.GetQueue).wait<Response.Queue>()?.let { response -> RequestBus.send(Request.GetQueue).wait<Response.Queue>()?.let { response ->
adapter?.let { adapter?.let {
it.data = response.queue.toMutableList() it.data = response.queue.toMutableList()
@ -63,7 +63,7 @@ class LandscapeQueueFragment : Fragment() {
} }
private fun watchEventBus() { private fun watchEventBus() {
GlobalScope.launch(Main) { activity?.lifecycleScope?.launch(Main) {
EventBus.get().collect { message -> EventBus.get().collect { message ->
when (message) { when (message) {
is Event.QueueChanged -> refresh() is Event.QueueChanged -> refresh()
@ -71,7 +71,7 @@ class LandscapeQueueFragment : Fragment() {
} }
} }
GlobalScope.launch(Main) { activity?.lifecycleScope?.launch(Main) {
CommandBus.get().collect { command -> CommandBus.get().collect { command ->
when (command) { when (command) {
is Command.RefreshTrack -> refresh() is Command.RefreshTrack -> refresh()

View File

@ -5,6 +5,7 @@ import android.view.Gravity
import android.view.View import android.view.View
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.PlaylistTracksAdapter import com.github.apognu.otter.adapters.PlaylistTracksAdapter
@ -15,7 +16,6 @@ import com.squareup.picasso.Picasso
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.android.synthetic.main.fragment_tracks.* import kotlinx.android.synthetic.main.fragment_tracks.*
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -73,7 +73,7 @@ class PlaylistTracksFragment : FunkwhaleFragment<PlaylistTrack, PlaylistTracksAd
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
RequestBus.send(Request.GetCurrentTrack).wait<Response.CurrentTrack>()?.let { response -> RequestBus.send(Request.GetCurrentTrack).wait<Response.CurrentTrack>()?.let { response ->
adapter.currentTrack = response.track adapter.currentTrack = response.track
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
@ -144,7 +144,7 @@ class PlaylistTracksFragment : FunkwhaleFragment<PlaylistTrack, PlaylistTracksAd
} }
imageView?.let { view -> imageView?.let { view ->
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
Picasso.get() Picasso.get()
.maybeLoad(maybeNormalizeUrl(url)) .maybeLoad(maybeNormalizeUrl(url))
.fit() .fit()
@ -157,7 +157,7 @@ class PlaylistTracksFragment : FunkwhaleFragment<PlaylistTrack, PlaylistTracksAd
} }
private fun watchEventBus() { private fun watchEventBus() {
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
CommandBus.get().collect { command -> CommandBus.get().collect { command ->
when (command) { when (command) {
is Command.RefreshTrack -> refreshCurrentTrack(command.track) is Command.RefreshTrack -> refreshCurrentTrack(command.track)

View File

@ -6,6 +6,7 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.TracksAdapter import com.github.apognu.otter.adapters.TracksAdapter
@ -18,7 +19,6 @@ import kotlinx.android.synthetic.main.fragment_queue.view.*
import kotlinx.android.synthetic.main.partial_queue.* import kotlinx.android.synthetic.main.partial_queue.*
import kotlinx.android.synthetic.main.partial_queue.view.* import kotlinx.android.synthetic.main.partial_queue.view.*
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -66,7 +66,7 @@ class QueueFragment : BottomSheetDialogFragment() {
} }
private fun refresh() { private fun refresh() {
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
RequestBus.send(Request.GetQueue).wait<Response.Queue>()?.let { response -> RequestBus.send(Request.GetQueue).wait<Response.Queue>()?.let { response ->
included?.let { included -> included?.let { included ->
adapter?.let { adapter?.let {
@ -87,7 +87,7 @@ class QueueFragment : BottomSheetDialogFragment() {
} }
private fun watchEventBus() { private fun watchEventBus() {
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
EventBus.get().collect { message -> EventBus.get().collect { message ->
when (message) { when (message) {
is Event.QueueChanged -> refresh() is Event.QueueChanged -> refresh()
@ -95,7 +95,7 @@ class QueueFragment : BottomSheetDialogFragment() {
} }
} }
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
CommandBus.get().collect { command -> CommandBus.get().collect { command ->
when (command) { when (command) {
is Command.RefreshTrack -> refresh() is Command.RefreshTrack -> refresh()

View File

@ -2,6 +2,7 @@ package com.github.apognu.otter.fragments
import android.os.Bundle import android.os.Bundle
import androidx.core.view.forEach import androidx.core.view.forEach
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.RadiosAdapter import com.github.apognu.otter.adapters.RadiosAdapter
@ -9,7 +10,6 @@ import com.github.apognu.otter.repositories.RadiosRepository
import com.github.apognu.otter.utils.* import com.github.apognu.otter.utils.*
import kotlinx.android.synthetic.main.fragment_radios.* import kotlinx.android.synthetic.main.fragment_radios.*
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -20,7 +20,7 @@ class RadiosFragment : FunkwhaleFragment<Radio, RadiosAdapter>() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
adapter = RadiosAdapter(context, RadioClickListener()) adapter = RadiosAdapter(context, lifecycleScope, RadioClickListener())
repository = RadiosRepository(context) repository = RadiosRepository(context)
} }
@ -34,15 +34,16 @@ class RadiosFragment : FunkwhaleFragment<Radio, RadiosAdapter>() {
CommandBus.send(Command.PlayRadio(radio)) CommandBus.send(Command.PlayRadio(radio))
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
EventBus.get().collect { message -> EventBus.get().collect { message ->
when (message) { when (message) {
is Event.RadioStarted -> is Event.RadioStarted ->
if (radios != null) { recycler.forEach { if (radios != null) {
it.isEnabled = true recycler.forEach {
it.isClickable = true it.isEnabled = true
it.isClickable = true
}
} }
}
} }
} }
} }

View File

@ -5,6 +5,7 @@ import android.view.Gravity
import android.view.View import android.view.View
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.apognu.otter.R import com.github.apognu.otter.R
import com.github.apognu.otter.adapters.TracksAdapter import com.github.apognu.otter.adapters.TracksAdapter
@ -17,7 +18,6 @@ import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
import kotlinx.android.synthetic.main.fragment_tracks.* import kotlinx.android.synthetic.main.fragment_tracks.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -81,12 +81,10 @@ class TracksFragment : FunkwhaleFragment<Track, TracksAdapter>() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
GlobalScope.launch(IO) { lifecycleScope.launch(Main) {
RequestBus.send(Request.GetCurrentTrack).wait<Response.CurrentTrack>()?.let { response -> RequestBus.send(Request.GetCurrentTrack).wait<Response.CurrentTrack>()?.let { response ->
withContext(Main) { adapter.currentTrack = response.track
adapter.currentTrack = response.track adapter.notifyDataSetChanged()
adapter.notifyDataSetChanged()
}
} }
refreshDownloadedTracks() refreshDownloadedTracks()
@ -138,7 +136,7 @@ class TracksFragment : FunkwhaleFragment<Track, TracksAdapter>() {
} }
private fun watchEventBus() { private fun watchEventBus() {
GlobalScope.launch(IO) { lifecycleScope.launch(IO) {
EventBus.get().collect { message -> EventBus.get().collect { message ->
when (message) { when (message) {
is Event.DownloadChanged -> refreshDownloadedTrack(message.download) is Event.DownloadChanged -> refreshDownloadedTrack(message.download)
@ -146,7 +144,7 @@ class TracksFragment : FunkwhaleFragment<Track, TracksAdapter>() {
} }
} }
GlobalScope.launch(Main) { lifecycleScope.launch(Main) {
CommandBus.get().collect { command -> CommandBus.get().collect { command ->
when (command) { when (command) {
is Command.RefreshTrack -> refreshCurrentTrack(command.track) is Command.RefreshTrack -> refreshCurrentTrack(command.track)

View File

@ -16,11 +16,11 @@ import com.github.apognu.otter.R
import com.github.apognu.otter.activities.MainActivity import com.github.apognu.otter.activities.MainActivity
import com.github.apognu.otter.utils.* import com.github.apognu.otter.utils.*
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Dispatchers.Default
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MediaControlsManager(val context: Service, private val mediaSession: MediaSessionCompat) { class MediaControlsManager(val context: Service, private val scope: CoroutineScope, private val mediaSession: MediaSessionCompat) {
companion object { companion object {
const val NOTIFICATION_ACTION_OPEN_QUEUE = 0 const val NOTIFICATION_ACTION_OPEN_QUEUE = 0
const val NOTIFICATION_ACTION_PREVIOUS = 1 const val NOTIFICATION_ACTION_PREVIOUS = 1
@ -39,7 +39,7 @@ class MediaControlsManager(val context: Service, private val mediaSession: Media
false -> R.drawable.play false -> R.drawable.play
} }
GlobalScope.launch(IO) { scope.launch(Default) {
val openIntent = Intent(context, MainActivity::class.java).apply { action = NOTIFICATION_ACTION_OPEN_QUEUE.toString() } val openIntent = Intent(context, MainActivity::class.java).apply { action = NOTIFICATION_ACTION_OPEN_QUEUE.toString() }
val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, 0) val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, 0)

View File

@ -14,13 +14,16 @@ import com.google.android.exoplayer2.offline.DownloadService
import com.google.android.exoplayer2.scheduler.Scheduler import com.google.android.exoplayer2.scheduler.Scheduler
import com.google.android.exoplayer2.ui.DownloadNotificationHelper import com.google.android.exoplayer2.ui.DownloadNotificationHelper
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.* import java.util.*
class PinService : DownloadService(AppContext.NOTIFICATION_DOWNLOADS) { class PinService : DownloadService(AppContext.NOTIFICATION_DOWNLOADS) {
private val scope: CoroutineScope = CoroutineScope(Job() + Main)
companion object { companion object {
fun download(context: Context, track: Track) { fun download(context: Context, track: Track) {
track.bestUpload()?.let { upload -> track.bestUpload()?.let { upload ->
@ -45,7 +48,7 @@ class PinService : DownloadService(AppContext.NOTIFICATION_DOWNLOADS) {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
buildResumeDownloadsIntent(this, PinService::class.java, true) buildResumeDownloadsIntent(this, PinService::class.java, true)
GlobalScope.launch(Main) { scope.launch(Main) {
RequestBus.get().collect { request -> RequestBus.get().collect { request ->
when (request) { when (request) {
is Request.GetDownloads -> request.channel?.offer(Response.Downloads(getDownloads())) is Request.GetDownloads -> request.channel?.offer(Response.Downloads(getDownloads()))

View File

@ -21,23 +21,24 @@ import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector
import com.google.android.exoplayer2.source.TrackGroupArray import com.google.android.exoplayer2.source.TrackGroupArray
import com.google.android.exoplayer2.trackselection.TrackSelectionArray import com.google.android.exoplayer2.trackselection.TrackSelectionArray
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class PlayerService : Service() { class PlayerService : Service() {
private lateinit var queue: QueueManager private var started = false
private val jobs = mutableListOf<Job>() private val scope: CoroutineScope = CoroutineScope(Job() + Main)
private lateinit var audioManager: AudioManager private lateinit var audioManager: AudioManager
private var audioFocusRequest: AudioFocusRequest? = null private var audioFocusRequest: AudioFocusRequest? = null
private val audioFocusChangeListener = AudioFocusChange() private val audioFocusChangeListener = AudioFocusChange()
private var stateWhenLostFocus = false private var stateWhenLostFocus = false
private lateinit var queue: QueueManager
private lateinit var mediaControlsManager: MediaControlsManager private lateinit var mediaControlsManager: MediaControlsManager
private lateinit var mediaSession: MediaSessionCompat private lateinit var mediaSession: MediaSessionCompat
private lateinit var player: SimpleExoPlayer private lateinit var player: SimpleExoPlayer
@ -50,7 +51,9 @@ class PlayerService : Service() {
private lateinit var radioPlayer: RadioPlayer private lateinit var radioPlayer: RadioPlayer
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (jobs.isEmpty()) watchEventBus() if (!started) watchEventBus()
started = true
return START_STICKY return START_STICKY
} }
@ -59,7 +62,7 @@ class PlayerService : Service() {
super.onCreate() super.onCreate()
queue = QueueManager(this) queue = QueueManager(this)
radioPlayer = RadioPlayer(this) radioPlayer = RadioPlayer(this, scope)
audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
@ -83,7 +86,7 @@ class PlayerService : Service() {
isActive = true isActive = true
} }
mediaControlsManager = MediaControlsManager(this, mediaSession) mediaControlsManager = MediaControlsManager(this, scope, mediaSession)
player = SimpleExoPlayer.Builder(this).build().apply { player = SimpleExoPlayer.Builder(this).build().apply {
playWhenReady = false playWhenReady = false
@ -127,7 +130,7 @@ class PlayerService : Service() {
} }
private fun watchEventBus() { private fun watchEventBus() {
jobs.add(GlobalScope.launch(Main) { scope.launch(Main) {
CommandBus.get().collect { command -> CommandBus.get().collect { command ->
when (command) { when (command) {
is Command.RefreshService -> { is Command.RefreshService -> {
@ -193,9 +196,9 @@ class PlayerService : Service() {
mediaControlsManager.tick() mediaControlsManager.tick()
} }
} }
}) }
jobs.add(GlobalScope.launch(Main) { scope.launch(Main) {
RequestBus.get().collect { request -> RequestBus.get().collect { request ->
when (request) { when (request) {
is Request.GetCurrentTrack -> request.channel?.offer(Response.CurrentTrack(queue.current())) is Request.GetCurrentTrack -> request.channel?.offer(Response.CurrentTrack(queue.current()))
@ -203,9 +206,9 @@ class PlayerService : Service() {
is Request.GetQueue -> request.channel?.offer(Response.Queue(queue.get())) is Request.GetQueue -> request.channel?.offer(Response.Queue(queue.get()))
} }
} }
}) }
jobs.add(GlobalScope.launch(Main) { scope.launch(Main) {
while (true) { while (true) {
delay(1000) delay(1000)
@ -215,18 +218,13 @@ class PlayerService : Service() {
ProgressBus.send(current, duration, percent) ProgressBus.send(current, duration, percent)
} }
} }
}) }
} }
override fun onBind(intent: Intent?): IBinder? = null override fun onBind(intent: Intent?): IBinder? = null
@SuppressLint("NewApi") @SuppressLint("NewApi")
override fun onDestroy() { override fun onDestroy() {
jobs.forEach {
it.cancel()
jobs.remove(it)
}
try { try {
unregisterReceiver(headphonesUnpluggedReceiver) unregisterReceiver(headphonesUnpluggedReceiver)
} catch (_: Exception) { } catch (_: Exception) {
@ -372,7 +370,7 @@ class PlayerService : Service() {
mediaControlsManager.updateNotification(queue.current(), player.playWhenReady) mediaControlsManager.updateNotification(queue.current(), player.playWhenReady)
if (queue.get().isNotEmpty() && queue.current() == queue.get().last() && radioPlayer.isActive()) { if (queue.get().isNotEmpty() && queue.current() == queue.get().last() && radioPlayer.isActive()) {
GlobalScope.launch(IO) { scope.launch(IO) {
if (radioPlayer.lock.tryAcquire()) { if (radioPlayer.lock.tryAcquire()) {
radioPlayer.prepareNextTrack() radioPlayer.prepareNextTrack()
radioPlayer.lock.release() radioPlayer.lock.release()

View File

@ -10,9 +10,9 @@ import com.github.kittinunf.fuel.coroutines.awaitObjectResponseResult
import com.github.kittinunf.fuel.coroutines.awaitObjectResult import com.github.kittinunf.fuel.coroutines.awaitObjectResult
import com.github.kittinunf.fuel.gson.gsonDeserializerOf import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -25,7 +25,7 @@ data class RadioTrackBody(val session: Int)
data class RadioTrack(val position: Int, val track: RadioTrackID) data class RadioTrack(val position: Int, val track: RadioTrackID)
data class RadioTrackID(val id: Int) data class RadioTrackID(val id: Int)
class RadioPlayer(val context: Context) { class RadioPlayer(val context: Context, val scope: CoroutineScope) {
val lock = Semaphore(1) val lock = Semaphore(1)
private var currentRadio: Radio? = null private var currentRadio: Radio? = null
@ -52,7 +52,7 @@ class RadioPlayer(val context: Context) {
currentRadio = radio currentRadio = radio
session = null session = null
GlobalScope.launch(IO) { scope.launch(IO) {
createSession() createSession()
} }
} }

View File

@ -9,7 +9,6 @@ import com.github.kittinunf.fuel.gson.gsonDeserializerOf
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import java.io.BufferedReader import java.io.BufferedReader
@ -47,7 +46,7 @@ class FavoritesRepository(override val context: Context?) : Repository<Track, Tr
} }
} }
GlobalScope.launch(IO) { scope.launch(IO) {
request request
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.body(Gson().toJson(body)) .body(Gson().toJson(body))
@ -64,7 +63,7 @@ class FavoritesRepository(override val context: Context?) : Repository<Track, Tr
} }
} }
GlobalScope.launch(IO) { scope.launch(IO) {
request request
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.body(Gson().toJson(body)) .body(Gson().toJson(body))

View File

@ -3,7 +3,9 @@ package com.github.apognu.otter.repositories
import android.content.Context import android.content.Context
import com.github.apognu.otter.utils.Cache import com.github.apognu.otter.utils.Cache
import com.github.apognu.otter.utils.CacheItem import com.github.apognu.otter.utils.CacheItem
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import java.io.BufferedReader import java.io.BufferedReader
@ -12,6 +14,8 @@ interface Upstream<D> {
} }
abstract class Repository<D : Any, C : CacheItem<D>> { abstract class Repository<D : Any, C : CacheItem<D>> {
protected val scope: CoroutineScope = CoroutineScope(Job() + IO)
enum class Origin(val origin: Int) { enum class Origin(val origin: Int) {
Cache(0b01), Cache(0b01),
Network(0b10) Network(0b10)

View File

@ -77,7 +77,7 @@ object EventBus {
object CommandBus { object CommandBus {
fun send(command: Command) { fun send(command: Command) {
GlobalScope.launch { GlobalScope.launch(IO) {
Otter.get().commandBus.offer(command) Otter.get().commandBus.offer(command)
} }
} }
@ -101,7 +101,7 @@ object RequestBus {
object ProgressBus { object ProgressBus {
fun send(current: Int, duration: Int, percent: Int) { fun send(current: Int, duration: Int, percent: Int) {
GlobalScope.launch { GlobalScope.launch(IO) {
Otter.get().progressBus.send(Triple(current, duration, percent)) Otter.get().progressBus.send(Triple(current, duration, percent))
} }
} }

View File

@ -10,15 +10,15 @@ import com.google.android.exoplayer2.offline.Download
import com.google.gson.Gson import com.google.gson.Gson
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import com.squareup.picasso.RequestCreator import com.squareup.picasso.RequestCreator
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
inline fun <D> Flow<Repository.Response<D>>.untilNetwork(context: CoroutineContext = Main, crossinline callback: (data: List<D>, isCache: Boolean, hasMore: Boolean) -> Unit) { inline fun <D> Flow<Repository.Response<D>>.untilNetwork(scope: CoroutineScope, context: CoroutineContext = Main, crossinline callback: (data: List<D>, isCache: Boolean, hasMore: Boolean) -> Unit) {
GlobalScope.launch(context) { scope.launch(context) {
collect { data -> collect { data ->
callback(data.data, data.origin == Repository.Origin.Cache, data.hasMore) callback(data.data, data.origin == Repository.Origin.Cache, data.hasMore)
} }

View File

@ -2,13 +2,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- <item
android:id="@+id/cast"
android:iconTint="@android:color/white"
android:title="@string/toolbar_cast"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
app:showAsAction="ifRoom" /> -->
<item <item
android:id="@+id/nav_search" android:id="@+id/nav_search"
android:icon="@drawable/search" android:icon="@drawable/search"

View File

@ -8,13 +8,6 @@
android:title="@string/playback_queue" android:title="@string/playback_queue"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<!-- <item
android:id="@+id/cast"
android:iconTint="@android:color/white"
android:title="@string/toolbar_cast"
app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
app:showAsAction="ifRoom" /> -->
<item <item
android:id="@+id/nav_search" android:id="@+id/nav_search"
android:icon="@drawable/search" android:icon="@drawable/search"