Initial suspend all db query

TODO: Cleanup DownloadManager
This commit is contained in:
tarsin committed 2023-07-12 12:21:05 +08:00
1 parent 179e470154
commit 25d876f8b9
7 files changed
+120 -103

No files matched your search

+10 -19
View File
@@ -36,23 +36,20 @@ import com.hippo.ehviewer.util.sendTo
import splitties.arch.room.roomDb
object EhDB {
private val db = roomDb<EhDatabase>("eh.db") { allowMainThreadQueries() }
private val db = roomDb<EhDatabase>("eh.db")
// Fix state
suspend fun getAllDownloadInfo() = db.downloadsDao().list().onEach {
if (it.state == DownloadInfo.STATE_WAIT || it.state == DownloadInfo.STATE_DOWNLOAD) {
it.state = DownloadInfo.STATE_NONE
}
}
@Synchronized
fun updateDownloadInfo(downloadInfos: List<DownloadInfo>) {
suspend fun updateDownloadInfo(downloadInfo: List<DownloadInfo>) {
val dao = db.downloadsDao()
dao.update(downloadInfos)
dao.update(downloadInfo)
}
@Synchronized
fun putDownloadInfo(downloadInfo: DownloadInfo) {
suspend fun putDownloadInfo(downloadInfo: DownloadInfo) {
db.downloadsDao().run {
if (load(downloadInfo.gid) != null) {
update(downloadInfo)
@@ -62,8 +59,7 @@ object EhDB {
}
}
@Synchronized
fun removeDownloadInfo(downloadInfo: DownloadInfo) {
suspend fun removeDownloadInfo(downloadInfo: DownloadInfo) {
db.downloadsDao().delete(downloadInfo)
}
@@ -111,11 +107,8 @@ object EhDB {
dao.update(raw)
}
@Synchronized
fun moveDownloadLabel(fromPosition: Int, toPosition: Int) {
if (fromPosition == toPosition) {
return
}
suspend fun moveDownloadLabel(fromPosition: Int, toPosition: Int) {
if (fromPosition == toPosition) return
val reverse = fromPosition > toPosition
val offset = if (reverse) toPosition else fromPosition
val limit = if (reverse) fromPosition - toPosition + 1 else toPosition - fromPosition + 1
@@ -126,7 +119,7 @@ object EhDB {
val end = if (reverse) 0 else limit - 1
val toTime = list[end].time
var i = end
while (if (reverse) i < start else i > start) {
while (if (reverse) i < start else i > 0) {
list[i].time = list[i + step].time
i += step
}
@@ -197,9 +190,7 @@ object EhDB {
}
suspend fun moveQuickSearch(fromPosition: Int, toPosition: Int) {
if (fromPosition == toPosition) {
return
}
if (fromPosition == toPosition) return
val reverse = fromPosition > toPosition
val offset = if (reverse) toPosition else fromPosition
val limit = if (reverse) fromPosition - toPosition + 1 else toPosition - fromPosition + 1
@@ -210,7 +201,7 @@ object EhDB {
val end = if (reverse) 0 else limit - 1
val toTime = list[end].time
var i = end
while (if (reverse) i < start else i > start) {
while (if (reverse) i < start else i > 0) {
list[i].time = list[i + step].time
i += step
}
@@ -12,10 +12,10 @@ interface DownloadLabelDao {
suspend fun list(): List<DownloadLabel>
@Query("SELECT * FROM DOWNLOAD_LABELS ORDER BY TIME ASC LIMIT :limit OFFSET :offset")
fun list(offset: Int, limit: Int): List<DownloadLabel>
suspend fun list(offset: Int, limit: Int): List<DownloadLabel>
@Update
fun update(downloadLabels: List<DownloadLabel>)
suspend fun update(downloadLabels: List<DownloadLabel>)
@Update
suspend fun update(downloadLabel: DownloadLabel)
@@ -12,20 +12,20 @@ interface DownloadsDao {
suspend fun list(): List<DownloadInfo>
@Query("SELECT * FROM DOWNLOADS ORDER BY TIME DESC LIMIT :limit OFFSET :offset")
fun list(offset: Int, limit: Int): List<DownloadInfo>
suspend fun list(offset: Int, limit: Int): List<DownloadInfo>
@Query("SELECT * FROM DOWNLOADS WHERE GID = :gid")
fun load(gid: Long): DownloadInfo?
suspend fun load(gid: Long): DownloadInfo?
@Update
fun update(downloadInfos: List<DownloadInfo>)
suspend fun update(downloadInfo: List<DownloadInfo>)
@Update
fun update(downloadInfo: DownloadInfo)
suspend fun update(downloadInfo: DownloadInfo)
@Insert
fun insert(t: DownloadInfo): Long
suspend fun insert(t: DownloadInfo): Long
@Delete
fun delete(downloadInfo: DownloadInfo)
suspend fun delete(downloadInfo: DownloadInfo)
}
@@ -137,7 +137,7 @@ object DownloadManager : OnSpiderListener {
mDownloadListener = listener
}
private fun ensureDownload() {
private suspend fun ensureDownload() {
if (mCurrentTask != null) {
// Only one download
return
@@ -175,7 +175,7 @@ object DownloadManager : OnSpiderListener {
}
}
fun startDownload(galleryInfo: GalleryInfo, label: String?) {
suspend fun startDownload(galleryInfo: GalleryInfo, label: String?) {
if (mCurrentTask != null && mCurrentTask!!.gid == galleryInfo.gid) {
// It is current task
return
@@ -240,7 +240,7 @@ object DownloadManager : OnSpiderListener {
}
}
fun startRangeDownload(gidList: LongList) {
suspend fun startRangeDownload(gidList: LongList) {
var update = false
for (i in 0 until gidList.size) {
val gid = gidList[i]
@@ -301,7 +301,7 @@ object DownloadManager : OnSpiderListener {
fun stateFlow(gid: Long) = _stateFlow.filter { it.gid == gid }
fun startAllDownload() {
suspend fun startAllDownload() {
var update = false
// Start all STATE_NONE and STATE_FAILED item
for (info in allInfoList) {
@@ -418,7 +418,7 @@ object DownloadManager : OnSpiderListener {
}
}
fun stopDownload(gid: Long) {
suspend fun stopDownload(gid: Long) {
val info = stopDownloadInternal(gid)
if (info != null) {
// Update listener
@@ -433,7 +433,7 @@ object DownloadManager : OnSpiderListener {
}
}
fun stopCurrentDownload() {
suspend fun stopCurrentDownload() {
val info = stopCurrentDownloadInternal()
if (info != null) {
// Update listener
@@ -448,7 +448,7 @@ object DownloadManager : OnSpiderListener {
}
}
fun stopRangeDownload(gidList: LongList) {
suspend fun stopRangeDownload(gidList: LongList) {
stopRangeDownloadInternal(gidList)
// Update listener
@@ -460,7 +460,7 @@ object DownloadManager : OnSpiderListener {
ensureDownload()
}
fun stopAllDownload() {
suspend fun stopAllDownload() {
// Stop all in wait list
for (info in mWaitList) {
info.state = DownloadInfo.STATE_NONE
@@ -478,7 +478,7 @@ object DownloadManager : OnSpiderListener {
}
}
fun deleteDownload(gid: Long) {
suspend fun deleteDownload(gid: Long) {
stopDownloadInternal(gid)
val info = mAllInfoMap[gid]
if (info != null) {
@@ -507,7 +507,7 @@ object DownloadManager : OnSpiderListener {
}
}
fun deleteRangeDownload(gidList: LongList) {
suspend fun deleteRangeDownload(gidList: LongList) {
stopRangeDownloadInternal(gidList)
for (i in 0 until gidList.size) {
val gid = gidList[i]
@@ -538,7 +538,7 @@ object DownloadManager : OnSpiderListener {
ensureDownload()
}
fun moveDownload(fromPosition: Int, toPosition: Int) {
suspend fun moveDownload(fromPosition: Int, toPosition: Int) {
if (fromPosition > toPosition) {
val time = allInfoList[toPosition].time
for (i in toPosition until fromPosition) {
@@ -560,7 +560,7 @@ object DownloadManager : OnSpiderListener {
list.sortByDateDescending()
}
fun moveDownload(label: String?, fromPosition: Int, toPosition: Int) {
suspend fun moveDownload(label: String?, fromPosition: Int, toPosition: Int) {
val list = getInfoListForLabel(label)
list?.let {
val absFromPosition = allInfoList.indexOf(it[fromPosition])
@@ -593,7 +593,7 @@ object DownloadManager : OnSpiderListener {
// Update in DB
// Update listener
// No ensureDownload
private fun stopDownloadInternal(gid: Long): DownloadInfo? {
private suspend fun stopDownloadInternal(gid: Long): DownloadInfo? {
// Check current task
if (mCurrentTask != null && mCurrentTask!!.gid == gid) {
// Stop current
@@ -617,7 +617,7 @@ object DownloadManager : OnSpiderListener {
// Update in DB
// Update mDownloadListener
private fun stopCurrentDownloadInternal(): DownloadInfo? {
private suspend fun stopCurrentDownloadInternal(): DownloadInfo? {
val info = mCurrentTask
val spider = mCurrentSpider
// Release spider
@@ -646,7 +646,7 @@ object DownloadManager : OnSpiderListener {
// Update in DB
// Update mDownloadListener
private fun stopRangeDownloadInternal(gidList: LongList) {
private suspend fun stopRangeDownloadInternal(gidList: LongList) {
// Two way
if (gidList.size < mWaitList.size) {
for (i in 0 until gidList.size) {
@@ -678,7 +678,7 @@ object DownloadManager : OnSpiderListener {
/**
* @param label Not allow new label
*/
fun changeLabel(list: List<DownloadInfo>, label: String?) {
suspend fun changeLabel(list: List<DownloadInfo>, label: String?) {
if (null != label && !containLabel(label)) {
Log.e(TAG, "Not exits label: $label")
return
@@ -718,7 +718,7 @@ object DownloadManager : OnSpiderListener {
map[label] = LinkedList()
}
fun moveLabel(fromPosition: Int, toPosition: Int) {
suspend fun moveLabel(fromPosition: Int, toPosition: Int) {
val item = labelList.removeAt(fromPosition)
labelList.add(toPosition, item)
EhDB.moveDownloadLabel(fromPosition, toPosition)
@@ -1077,24 +1077,26 @@ object DownloadManager : OnSpiderListener {
} else {
info.state = DownloadInfo.STATE_FAILED
}
// Update in DB
EhDB.putDownloadInfo(info)
// Notify
if (mDownloadListener != null) {
mDownloadListener!!.onFinish(info)
}
val list: List<DownloadInfo>? = getInfoListForLabel(info.label)
if (list != null) {
for (l in mDownloadInfoListeners) {
l.onUpdate(info, list)
launchIO {
// Update in DB
EhDB.putDownloadInfo(info)
// Notify
if (mDownloadListener != null) {
mDownloadListener!!.onFinish(info)
}
val list: List<DownloadInfo>? = getInfoListForLabel(info.label)
if (list != null) {
for (l in mDownloadInfoListeners) {
l.onUpdate(info, list)
}
}
// Start next download
ensureDownload()
}
// Start next download
ensureDownload()
}
}
}
mNotifyTaskPool.push(this)
if (mType != TYPE_ON_FINISH) mNotifyTaskPool.push(this)
}
}
@@ -21,7 +21,6 @@ import android.app.Service
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.IBinder
import android.os.SystemClock
import android.util.Log
import androidx.annotation.IntDef
@@ -41,8 +40,13 @@ import com.hippo.ehviewer.util.LongList
import com.hippo.ehviewer.util.ReadableTime
import com.hippo.ehviewer.util.SimpleHandler
import com.hippo.ehviewer.util.getParcelableExtraCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
class DownloadService : Service(), DownloadManager.DownloadListener {
class DownloadService : Service(), DownloadManager.DownloadListener, CoroutineScope {
override val coroutineContext = Dispatchers.IO + SupervisorJob()
private var mNotifyManager: NotificationManagerCompat? = null
private var mDownloadManager: DownloadManager? = null
private var mDownloadingBuilder: NotificationCompat.Builder? = null
@@ -88,11 +92,11 @@ class DownloadService : Service(), DownloadManager.DownloadListener {
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
handleIntent(intent)
launch { handleIntent(intent) }
return START_STICKY
}
private fun handleIntent(intent: Intent?) {
private suspend fun handleIntent(intent: Intent?) {
when (intent?.action) {
ACTION_START -> {
val gi = intent.getParcelableExtraCompat<GalleryInfo>(KEY_GALLERY_INFO)
@@ -162,9 +166,7 @@ class DownloadService : Service(), DownloadManager.DownloadListener {
checkStopSelf()
}
override fun onBind(intent: Intent): IBinder? {
throw IllegalStateException("No bindService")
}
override fun onBind(intent: Intent) = error("No bindService")
private fun ensureDownloadingBuilder() {
if (mDownloadingBuilder != null) {
@@ -237,15 +239,17 @@ class DownloadService : Service(), DownloadManager.DownloadListener {
}
override fun onGet509() {
if (mDownloadManager != null) {
mDownloadManager!!.stopAllDownload()
launch {
if (mDownloadManager != null) {
mDownloadManager!!.stopAllDownload()
}
if (mNotifyManager == null) {
return@launch
}
ensure509Builder()
m509dBuilder!!.setWhen(System.currentTimeMillis())
m509Delay!!.show()
}
if (mNotifyManager == null) {
return
}
ensure509Builder()
m509dBuilder!!.setWhen(System.currentTimeMillis())
m509Delay!!.show()
}
override fun onStart(info: DownloadInfo) {
@@ -370,7 +370,9 @@ class DownloadsScene :
}
R.id.action_stop_all -> {
DownloadManager.stopAllDownload()
lifecycleScope.launchIO {
DownloadManager.stopAllDownload()
}
return true
}
@@ -564,10 +566,14 @@ class DownloadsScene :
}
2 -> {
// Stop
DownloadManager.stopRangeDownload(gidList!!)
// Cancel check mode
binding.recyclerView.outOfCustomChoiceMode()
lifecycleScope.launchIO {
// Stop
DownloadManager.stopRangeDownload(gidList!!)
withUIContext {
// Cancel check mode
binding.recyclerView.outOfCustomChoiceMode()
}
}
}
3 -> {
@@ -611,10 +617,12 @@ class DownloadsScene :
if (mList !== list) {
return
}
if (mAdapter != null) {
mAdapter!!.notifyItemInserted(position)
lifecycleScope.launchUI {
if (mAdapter != null) {
mAdapter!!.notifyItemInserted(position)
}
updateView()
}
updateView()
}
override fun onUpdate(info: DownloadInfo, list: List<DownloadInfo>) {
@@ -622,15 +630,19 @@ class DownloadsScene :
return
}
val index = mList!!.indexOf(info)
if (index >= 0 && mAdapter != null) {
mAdapter!!.notifyItemChanged(index, PAYLOAD_STATE)
lifecycleScope.launchUI {
if (index >= 0 && mAdapter != null) {
mAdapter!!.notifyItemChanged(index, PAYLOAD_STATE)
}
}
}
@SuppressLint("NotifyDataSetChanged")
override fun onUpdateAll() {
if (mAdapter != null) {
mAdapter!!.notifyDataSetChanged()
lifecycleScope.launchUI {
if (mAdapter != null) {
mAdapter!!.notifyDataSetChanged()
}
}
}
@@ -648,10 +660,12 @@ class DownloadsScene :
if (mList !== list) {
return
}
if (mAdapter != null) {
mAdapter!!.notifyItemRemoved(position)
lifecycleScope.launchUI {
if (mAdapter != null) {
mAdapter!!.notifyItemRemoved(position)
}
updateView()
}
updateView()
}
private class DownloadLabelHolder(val binding: ItemDrawerListBinding) :
@@ -748,14 +762,13 @@ class DownloadsScene :
// Cancel check mode
binding.recyclerView.outOfCustomChoiceMode()
// Delete
DownloadManager.deleteRangeDownload(mGidList)
// Delete image files
val checked = mBuilder.isChecked
Settings.removeImageFiles = checked
if (checked) {
lifecycleScope.launchIO {
// Delete
DownloadManager.deleteRangeDownload(mGidList)
val files = arrayOfNulls<UniFile>(mDownloadInfoList.size)
for ((i, info) in mDownloadInfoList.withIndex()) {
// Put file
@@ -784,9 +797,13 @@ class DownloadsScene :
} else {
mLabels[which]
}
downloadManager.changeLabel(mDownloadInfoList, label)
if (mLabelAdapter != null) {
mLabelAdapter!!.notifyDataSetChanged()
lifecycleScope.launchIO {
downloadManager.changeLabel(mDownloadInfoList, label)
withUIContext {
if (mLabelAdapter != null) {
mLabelAdapter!!.notifyDataSetChanged()
}
}
}
}
}
@@ -833,7 +850,9 @@ class DownloadsScene :
}
binding.stop -> {
DownloadManager.stopDownload(list[index].gid)
lifecycleScope.launchIO {
DownloadManager.stopDownload(list[index].gid)
}
}
}
}
@@ -1133,7 +1152,9 @@ class DownloadsScene :
if (null == context || fromPosition == toPosition || toPosition < LABEL_OFFSET) {
return false
}
downloadManager.moveLabel(fromPosition - LABEL_OFFSET, toPosition - LABEL_OFFSET)
lifecycleScope.launchIO {
downloadManager.moveLabel(fromPosition - LABEL_OFFSET, toPosition - LABEL_OFFSET)
}
val item = mLabels.removeAt(fromPosition)
mLabels.add(toPosition, item)
mLabelAdapter!!.notifyItemMoved(fromPosition, toPosition)
@@ -1264,14 +1264,13 @@ class GalleryDetailScene : BaseScene() {
return
}
// Delete
EhDownloadManager.deleteDownload(mGalleryInfo.gid)
// Delete image files
val checked = mBuilder.isChecked
Settings.removeImageFiles = checked
if (checked) {
lifecycleScope.launchIO {
lifecycleScope.launchIO {
// Delete
EhDownloadManager.deleteDownload(mGalleryInfo.gid)
// Delete image files
val checked = mBuilder.isChecked
Settings.removeImageFiles = checked
if (checked) {
runCatching {
val file = getGalleryDownloadDir(mGalleryInfo.gid)
EhDB.removeDownloadDirname(mGalleryInfo.gid)