Fix DownloadService leak

pull/211/head
Koitharu 4 years ago
parent 9c740c5cc1
commit d5bea0ca53
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -9,6 +9,8 @@ import android.os.IBinder
import android.os.PowerManager import android.os.PowerManager
import android.widget.Toast import android.widget.Toast
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -41,7 +43,6 @@ class DownloadService : BaseService() {
private val jobs = LinkedHashMap<Int, PausingProgressJob<DownloadState>>() private val jobs = LinkedHashMap<Int, PausingProgressJob<DownloadState>>()
private val jobCount = MutableStateFlow(0) private val jobCount = MutableStateFlow(0)
private val controlReceiver = ControlReceiver() private val controlReceiver = ControlReceiver()
private var binder: DownloadBinder? = null
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@ -50,7 +51,7 @@ class DownloadService : BaseService() {
val wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager) val wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager)
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "kotatsu:downloading") .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "kotatsu:downloading")
downloadManager = get<DownloadManager.Factory>().create( downloadManager = get<DownloadManager.Factory>().create(
coroutineScope = lifecycleScope + WakeLockNode(wakeLock, TimeUnit.HOURS.toMillis(1)) coroutineScope = lifecycleScope + WakeLockNode(wakeLock, TimeUnit.HOURS.toMillis(1)),
) )
DownloadNotification.createChannel(this) DownloadNotification.createChannel(this)
val intentFilter = IntentFilter() val intentFilter = IntentFilter()
@ -75,17 +76,11 @@ class DownloadService : BaseService() {
override fun onBind(intent: Intent): IBinder { override fun onBind(intent: Intent): IBinder {
super.onBind(intent) super.onBind(intent)
return binder ?: DownloadBinder(this).also { binder = it } return DownloadBinder(this)
}
override fun onUnbind(intent: Intent?): Boolean {
binder = null
return super.onUnbind(intent)
} }
override fun onDestroy() { override fun onDestroy() {
unregisterReceiver(controlReceiver) unregisterReceiver(controlReceiver)
binder = null
isRunning = false isRunning = false
super.onDestroy() super.onDestroy()
} }
@ -126,7 +121,7 @@ class DownloadService : BaseService() {
(job.progressValue as? DownloadState.Done)?.let { (job.progressValue as? DownloadState.Done)?.let {
sendBroadcast( sendBroadcast(
Intent(ACTION_DOWNLOAD_COMPLETE) Intent(ACTION_DOWNLOAD_COMPLETE)
.putExtra(EXTRA_MANGA, ParcelableManga(it.localManga, withChapters = false)) .putExtra(EXTRA_MANGA, ParcelableManga(it.localManga, withChapters = false)),
) )
} }
notificationSwitcher.detach( notificationSwitcher.detach(
@ -135,7 +130,7 @@ class DownloadService : BaseService() {
null null
} else { } else {
notification.create(job.progressValue, -1L) notification.create(job.progressValue, -1L)
} },
) )
stopSelf(startId) stopSelf(startId)
} }
@ -167,10 +162,25 @@ class DownloadService : BaseService() {
} }
} }
class DownloadBinder(private val service: DownloadService) : Binder() { class DownloadBinder(service: DownloadService) : Binder(), DefaultLifecycleObserver {
private var downloadsStateFlow = MutableStateFlow<Collection<PausingProgressJob<DownloadState>>>(emptyList())
init {
service.lifecycle.addObserver(this)
service.jobCount.onEach {
downloadsStateFlow.value = service.jobs.values
}.launchIn(service.lifecycleScope)
}
override fun onDestroy(owner: LifecycleOwner) {
owner.lifecycle.removeObserver(this)
downloadsStateFlow.value = emptyList()
super.onDestroy(owner)
}
val downloads: Flow<Collection<ProgressJob<DownloadState>>> val downloads
get() = service.jobCount.mapLatest { service.jobs.values } get() = downloadsStateFlow.asStateFlow()
} }
companion object { companion object {

Loading…
Cancel
Save