Skip to content

Commit

Permalink
Fix import book slow
Browse files Browse the repository at this point in the history
  • Loading branch information
821938089 committed Jan 21, 2025
1 parent 17a8608 commit c37c5d4
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 57 deletions.
7 changes: 5 additions & 2 deletions app/src/main/java/io/legado/app/data/dao/BookDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,11 @@ interface BookDao {
@Query("select 1 from books where bookUrl = :bookUrl")
fun has(bookUrl: String): Boolean?

@Query("select 1 from books where originName = :fileName or origin like '%' || :fileName")
fun hasFile(fileName: String): Boolean?
@Query(
"""select exists(select 1 from books where type & ${BookType.local} > 0
and (originName = :fileName or (origin != '${BookType.localTag}' and origin like '%' || :fileName)))"""
)
fun hasFile(fileName: String): Boolean

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg book: Book)
Expand Down
1 change: 0 additions & 1 deletion app/src/main/java/io/legado/app/data/entities/Book.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import io.legado.app.help.book.BookHelp
import io.legado.app.help.book.ContentProcessor
import io.legado.app.help.book.isEpub
import io.legado.app.help.book.isImage
import io.legado.app.help.book.isPdf
import io.legado.app.help.book.simulatedTotalChapterNum
import io.legado.app.help.config.AppConfig
import io.legado.app.help.config.ReadBookConfig
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/io/legado/app/ui/book/import/local/ImportBook.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.legado.app.ui.book.import.local

import io.legado.app.model.localBook.LocalBook
import io.legado.app.utils.FileDoc

data class ImportBook(
val file: FileDoc,
var isOnBookShelf: Boolean = LocalBook.isOnBookShelf(file.name)
) {
val name get() = file.name
val isDir get() = file.isDir
val size get() = file.size
val lastModified get() = file.lastModified
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),

override fun onMenuItemClick(item: MenuItem?): Boolean {
when (item?.itemId) {
R.id.menu_del_selection -> viewModel.deleteDoc(adapter.selectedUris) {
R.id.menu_del_selection -> viewModel.deleteDoc(adapter.selected) {
adapter.removeSelection()
}
}
Expand All @@ -118,8 +118,11 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),

@SuppressLint("NotifyDataSetChanged")
override fun onClickSelectBarMainAction() {
viewModel.addToBookshelf(adapter.selectedUris) {
adapter.selectedUris.clear()
viewModel.addToBookshelf(adapter.selected) {
adapter.selected.forEach {
it.isOnBookShelf = true
}
adapter.selected.clear()
adapter.notifyDataSetChanged()
}
}
Expand All @@ -129,6 +132,7 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
binding.tvEmptyMsg.setText(R.string.empty_msg_import_book)
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = adapter
binding.recyclerView.recycledViewPool.setMaxRecycledViews(0, 15)
binding.selectActionBar.setMainActionText(R.string.add_to_bookshelf)
binding.selectActionBar.inflateMenu(R.menu.import_book_sel)
binding.selectActionBar.setOnMenuItemClickListener(this)
Expand Down Expand Up @@ -212,7 +216,7 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
viewModel.sort = sort
putPrefInt(PreferKey.localBookImportSort, sort)
if (scanDocJob?.isActive != true) {
viewModel.dataCallback?.setItems(adapter.getItems())
viewModel.dataCallback?.upAdapter()
}
}

Expand All @@ -234,7 +238,7 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
path = path + doc.name + File.separator
}
binding.tvPath.text = path
adapter.selectedUris.clear()
adapter.selected.clear()
adapter.clearItems()
viewModel.loadDoc(lastDoc)
}
Expand Down Expand Up @@ -295,7 +299,7 @@ class ImportBookActivity : BaseImportBookActivity<ImportBookViewModel>(),
}

override fun upCountView() {
binding.selectActionBar.upCountView(adapter.selectedUris.size, adapter.checkableCount)
binding.selectActionBar.upCountView(adapter.selected.size, adapter.checkableCount)
}

override fun startRead(fileDoc: FileDoc) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ import io.legado.app.base.adapter.RecyclerAdapter
import io.legado.app.constant.AppConst
import io.legado.app.databinding.ItemImportBookBinding
import io.legado.app.model.localBook.LocalBook
import io.legado.app.utils.*
import io.legado.app.utils.ConvertUtils
import io.legado.app.utils.FileDoc
import io.legado.app.utils.gone
import io.legado.app.utils.invisible
import io.legado.app.utils.visible
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job


class ImportBookAdapter(context: Context, val callBack: CallBack) :
RecyclerAdapter<FileDoc, ItemImportBookBinding>(context) {
val selectedUris = hashSetOf<String>()
RecyclerAdapter<ImportBook, ItemImportBookBinding>(context) {
val selected = hashSetOf<ImportBook>()
var checkableCount = 0

override fun getViewBinding(parent: ViewGroup): ItemImportBookBinding {
Expand All @@ -28,7 +34,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
override fun convert(
holder: ItemViewHolder,
binding: ItemImportBookBinding,
item: FileDoc,
item: ImportBook,
payloads: MutableList<Any>
) {
binding.run {
Expand All @@ -40,7 +46,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
llBrief.gone()
cbSelect.isChecked = false
} else {
if (isOnBookShelf(item)) {
if (item.isOnBookShelf) {
ivIcon.setImageResource(R.drawable.ic_book_has)
ivIcon.visible()
cbSelect.invisible()
Expand All @@ -52,11 +58,11 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
tvTag.text = item.name.substringAfterLast(".")
tvSize.text = ConvertUtils.formatFileSize(item.size)
tvDate.text = AppConst.dateFormat.format(item.lastModified)
cbSelect.isChecked = selectedUris.contains(item.toString())
cbSelect.isChecked = selected.contains(item)
}
tvName.text = item.name
} else {
cbSelect.isChecked = selectedUris.contains(item.toString())
cbSelect.isChecked = selected.contains(item)
}
}
}
Expand All @@ -65,18 +71,18 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
holder.itemView.setOnClickListener {
getItem(holder.layoutPosition)?.let {
if (it.isDir) {
callBack.nextDoc(it)
} else if (!isOnBookShelf(it)) {
if (!selectedUris.contains(it.toString())) {
selectedUris.add(it.toString())
callBack.nextDoc(it.file)
} else if (!it.isOnBookShelf) {
if (!selected.contains(it)) {
selected.add(it)
} else {
selectedUris.remove(it.toString())
selected.remove(it)
}
notifyItemChanged(holder.layoutPosition, true)
callBack.upCountView()
} else {
/* 点击开始阅读 */
callBack.startRead(it)
callBack.startRead(it.file)
}
}
}
Expand All @@ -89,7 +95,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
private fun upCheckableCount() {
checkableCount = 0
getItems().forEach {
if (!it.isDir && !isOnBookShelf(it)) {
if (!it.isDir && !it.isOnBookShelf) {
checkableCount++
}
}
Expand All @@ -100,24 +106,24 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :
fun selectAll(selectAll: Boolean) {
if (selectAll) {
getItems().forEach {
if (!it.isDir && !isOnBookShelf(it)) {
selectedUris.add(it.toString())
if (!it.isDir && !it.isOnBookShelf) {
selected.add(it)
}
}
} else {
selectedUris.clear()
selected.clear()
}
notifyDataSetChanged()
callBack.upCountView()
}

fun revertSelection() {
getItems().forEach {
if (!it.isDir && !isOnBookShelf(it)) {
if (selectedUris.contains(it.toString())) {
selectedUris.remove(it.toString())
if (!it.isDir && !it.isOnBookShelf) {
if (selected.contains(it)) {
selected.remove(it)
} else {
selectedUris.add(it.toString())
selected.add(it)
}
}
}
Expand All @@ -127,7 +133,7 @@ class ImportBookAdapter(context: Context, val callBack: CallBack) :

fun removeSelection() {
for (i in getItems().lastIndex downTo 0) {
if (getItem(i)?.toString() in selectedUris) {
if (getItem(i) in selected) {
removeItem(i)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package io.legado.app.ui.book.import.local

import android.app.Application
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import io.legado.app.base.BaseViewModel
import io.legado.app.constant.AppLog
import io.legado.app.constant.AppPattern.archiveFileRegex
Expand All @@ -11,19 +9,19 @@ import io.legado.app.constant.PreferKey
import io.legado.app.model.localBook.LocalBook
import io.legado.app.utils.AlphanumComparator
import io.legado.app.utils.FileDoc
import io.legado.app.utils.delete
import io.legado.app.utils.getPrefInt
import io.legado.app.utils.isContentScheme
import io.legado.app.utils.list
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.isActive
import kotlinx.coroutines.withContext
import java.io.File
import java.util.Collections
import kotlin.coroutines.coroutineContext

Expand All @@ -33,20 +31,24 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
var sort = context.getPrefInt(PreferKey.localBookImportSort)
var dataCallback: DataCallback? = null
var dataFlowStart: (() -> Unit)? = null
val dataFlow = callbackFlow<List<FileDoc>> {
val dataFlow = callbackFlow<List<ImportBook>> {

val list = Collections.synchronizedList(ArrayList<FileDoc>())
val list = Collections.synchronizedList(ArrayList<ImportBook>())

dataCallback = object : DataCallback {

override fun setItems(fileDocs: List<FileDoc>) {
list.clear()
list.addAll(fileDocs)
fileDocs.mapTo(list) {
ImportBook(it)
}
trySend(list)
}

override fun addItems(fileDocs: List<FileDoc>) {
list.addAll(fileDocs)
fileDocs.mapTo(list) {
ImportBook(it)
}
trySend(list)
}

Expand All @@ -64,6 +66,10 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
)
}
}

override fun upAdapter() {
trySend(list)
}
}

withContext(Main) {
Expand All @@ -76,21 +82,17 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)

}.map { docList ->
val comparator = when (sort) {
2 -> compareBy<FileDoc>({ !it.isDir }, { -it.lastModified })
2 -> compareBy<ImportBook>({ !it.isDir }, { -it.lastModified })
1 -> compareBy({ !it.isDir }, { -it.size })
else -> compareBy { !it.isDir }
} then compareBy(AlphanumComparator) { it.name }
docList.sortedWith(comparator)
}.flowOn(IO)

fun addToBookshelf(uriList: HashSet<String>, finally: () -> Unit) {
fun addToBookshelf(bookList: HashSet<ImportBook>, finally: () -> Unit) {
execute {
val fileUris = uriList.map {
if (it.isContentScheme()) {
Uri.parse(it)
} else {
Uri.fromFile(File(it))
}
val fileUris = bookList.map {
it.file.uri
}
LocalBook.importFiles(fileUris)
}.onError {
Expand All @@ -101,17 +103,10 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)
}
}

fun deleteDoc(uriList: HashSet<String>, finally: () -> Unit) {
fun deleteDoc(bookList: HashSet<ImportBook>, finally: () -> Unit) {
execute {
uriList.forEach {
val uri = Uri.parse(it)
if (uri.isContentScheme()) {
DocumentFile.fromSingleUri(context, uri)?.delete()
} else {
uri.path?.let { path ->
File(path).delete()
}
}
bookList.forEach {
it.file.delete()
}
}.onFinally {
finally.invoke()
Expand Down Expand Up @@ -190,6 +185,8 @@ class ImportBookViewModel(application: Application) : BaseViewModel(application)

fun screen(key: String?)

fun upAdapter()

}

}

0 comments on commit c37c5d4

Please sign in to comment.