优化下载

pull/1298/head
gedoor 3 years ago
parent 8b7e4366d9
commit 2977b2aab4
  1. 17
      app/src/main/java/io/legado/app/model/CacheBook.kt
  2. 1
      app/src/main/java/io/legado/app/service/CacheBookService.kt
  3. 9
      app/src/main/java/io/legado/app/ui/book/cache/CacheActivity.kt
  4. 22
      app/src/main/java/io/legado/app/ui/book/cache/CacheAdapter.kt

@ -2,6 +2,7 @@ package io.legado.app.model
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import io.legado.app.constant.EventBus
import io.legado.app.constant.IntentAction import io.legado.app.constant.IntentAction
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
@ -10,10 +11,12 @@ import io.legado.app.data.entities.BookSource
import io.legado.app.help.BookHelp import io.legado.app.help.BookHelp
import io.legado.app.model.webBook.WebBook import io.legado.app.model.webBook.WebBook
import io.legado.app.service.CacheBookService import io.legado.app.service.CacheBookService
import io.legado.app.utils.postEvent
import io.legado.app.utils.startService import io.legado.app.utils.startService
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -22,7 +25,7 @@ class CacheBook(val bookSource: BookSource, val book: Book) {
companion object { companion object {
val logs = arrayListOf<String>() val logs = arrayListOf<String>()
val cacheBookMap = hashMapOf<String, CacheBook>() val cacheBookMap = ConcurrentHashMap<String, CacheBook>()
@SuppressLint("ConstantLocale") @SuppressLint("ConstantLocale")
private val logTimeFormat = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault()) private val logTimeFormat = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault())
@ -83,6 +86,8 @@ class CacheBook(val bookSource: BookSource, val book: Book) {
} }
} }
val isRun: Boolean get() = waitDownloadCount > 0 || onDownloadCount > 0
val waitDownloadCount: Int val waitDownloadCount: Int
get() { get() {
var count = 0 var count = 0
@ -113,8 +118,8 @@ class CacheBook(val bookSource: BookSource, val book: Book) {
} }
val waitDownloadSet = CopyOnWriteArraySet<Int>() val waitDownloadSet = CopyOnWriteArraySet<Int>()
val successDownloadSet = CopyOnWriteArraySet<Int>()
val onDownloadSet = CopyOnWriteArraySet<Int>() val onDownloadSet = CopyOnWriteArraySet<Int>()
val successDownloadSet = CopyOnWriteArraySet<Int>()
fun addDownload(start: Int, end: Int) { fun addDownload(start: Int, end: Int) {
for (i in start..end) { for (i in start..end) {
@ -122,6 +127,10 @@ class CacheBook(val bookSource: BookSource, val book: Book) {
} }
} }
fun isRun(): Boolean {
return waitDownloadSet.size > 0 || onDownloadSet.size > 0
}
@Synchronized @Synchronized
fun download(scope: CoroutineScope, context: CoroutineContext): Boolean { fun download(scope: CoroutineScope, context: CoroutineContext): Boolean {
val chapterIndex = waitDownloadSet.firstOrNull() ?: return false val chapterIndex = waitDownloadSet.firstOrNull() ?: return false
@ -158,6 +167,10 @@ class CacheBook(val bookSource: BookSource, val book: Book) {
}.onCancel { }.onCancel {
onDownloadSet.remove(chapterIndex) onDownloadSet.remove(chapterIndex)
waitDownloadSet.add(chapterIndex) waitDownloadSet.add(chapterIndex)
}.onFinally {
if (waitDownloadSet.isEmpty() && onDownloadSet.isEmpty()) {
postEvent(EventBus.UP_DOWNLOAD, "")
}
} }
return true return true
} }

@ -66,6 +66,7 @@ class CacheBookService : BaseService() {
override fun onDestroy() { override fun onDestroy() {
cachePool.close() cachePool.close()
CacheBook.cacheBookMap.clear()
super.onDestroy() super.onDestroy()
postEvent(EventBus.UP_DOWNLOAD, "") postEvent(EventBus.UP_DOWNLOAD, "")
} }

@ -35,8 +35,6 @@ 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
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet
class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>(), class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>(),
CacheAdapter.CallBack { CacheAdapter.CallBack {
@ -113,7 +111,7 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean { override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.menu_download -> { R.id.menu_download -> {
if (adapter.downloadMap.isNullOrEmpty()) { if (!CacheBook.isRun) {
adapter.getItems().forEach { book -> adapter.getItems().forEach { book ->
CacheBook.start( CacheBook.start(
this@CacheActivity, this@CacheActivity,
@ -212,15 +210,14 @@ class CacheActivity : VMBaseActivity<ActivityCacheBookBinding, CacheViewModel>()
} }
override fun observeLiveBus() { override fun observeLiveBus() {
observeEvent<ConcurrentHashMap<String, CopyOnWriteArraySet<BookChapter>>>(EventBus.UP_DOWNLOAD) { observeEvent<String>(EventBus.UP_DOWNLOAD) {
if (it.isEmpty()) { if (!CacheBook.isRun) {
menu?.findItem(R.id.menu_download)?.setIcon(R.drawable.ic_play_24dp) menu?.findItem(R.id.menu_download)?.setIcon(R.drawable.ic_play_24dp)
menu?.applyTint(this) menu?.applyTint(this)
} else { } else {
menu?.findItem(R.id.menu_download)?.setIcon(R.drawable.ic_stop_black_24dp) menu?.findItem(R.id.menu_download)?.setIcon(R.drawable.ic_stop_black_24dp)
menu?.applyTint(this) menu?.applyTint(this)
} }
adapter.downloadMap = it
adapter.notifyItemRangeChanged(0, adapter.itemCount, true) adapter.notifyItemRangeChanged(0, adapter.itemCount, true)
} }
observeEvent<BookChapter>(EventBus.SAVE_CONTENT) { observeEvent<BookChapter>(EventBus.SAVE_CONTENT) {

@ -7,19 +7,13 @@ import io.legado.app.R
import io.legado.app.base.adapter.ItemViewHolder import io.legado.app.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.RecyclerAdapter import io.legado.app.base.adapter.RecyclerAdapter
import io.legado.app.data.entities.Book import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.databinding.ItemDownloadBinding import io.legado.app.databinding.ItemDownloadBinding
import io.legado.app.model.CacheBook import io.legado.app.model.CacheBook
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet
class CacheAdapter(context: Context, private val callBack: CallBack) : class CacheAdapter(context: Context, private val callBack: CallBack) :
RecyclerAdapter<Book, ItemDownloadBinding>(context) { RecyclerAdapter<Book, ItemDownloadBinding>(context) {
val cacheChapters = hashMapOf<String, HashSet<String>>() val cacheChapters = hashMapOf<String, HashSet<String>>()
var downloadMap: ConcurrentHashMap<String, CopyOnWriteArraySet<BookChapter>>? = null
override fun getViewBinding(parent: ViewGroup): ItemDownloadBinding { override fun getViewBinding(parent: ViewGroup): ItemDownloadBinding {
return ItemDownloadBinding.inflate(inflater, parent, false) return ItemDownloadBinding.inflate(inflater, parent, false)
@ -55,11 +49,15 @@ class CacheAdapter(context: Context, private val callBack: CallBack) :
override fun registerListener(holder: ItemViewHolder, binding: ItemDownloadBinding) { override fun registerListener(holder: ItemViewHolder, binding: ItemDownloadBinding) {
binding.run { binding.run {
ivDownload.setOnClickListener { ivDownload.setOnClickListener {
getItem(holder.layoutPosition)?.let { getItem(holder.layoutPosition)?.let { book ->
if (downloadMap?.containsKey(it.bookUrl) == true) { CacheBook.get(book.bookUrl)?.let {
CacheBook.remove(context, it.bookUrl) if (it.isRun()) {
CacheBook.remove(context, book.bookUrl)
} else { } else {
CacheBook.start(context, it.bookUrl, 0, it.totalChapterNum) CacheBook.start(context, book.bookUrl, 0, book.totalChapterNum)
}
} ?: let {
CacheBook.start(context, book.bookUrl, 0, book.totalChapterNum)
} }
} }
} }
@ -70,8 +68,8 @@ class CacheAdapter(context: Context, private val callBack: CallBack) :
} }
private fun upDownloadIv(iv: ImageView, book: Book) { private fun upDownloadIv(iv: ImageView, book: Book) {
downloadMap?.let { CacheBook.get(book.bookUrl)?.let {
if (it.containsKey(book.bookUrl)) { if (it.isRun()) {
iv.setImageResource(R.drawable.ic_stop_black_24dp) iv.setImageResource(R.drawable.ic_stop_black_24dp)
} else { } else {
iv.setImageResource(R.drawable.ic_play_24dp) iv.setImageResource(R.drawable.ic_play_24dp)

Loading…
Cancel
Save