try to use flow

pull/1251/head
Jason Yao 3 years ago
parent 7ac00c1e74
commit b5308524db
  1. 1
      app/src/main/java/io/legado/app/constant/EventBus.kt
  2. 22
      app/src/main/java/io/legado/app/model/Debug.kt
  3. 16
      app/src/main/java/io/legado/app/service/CheckSourceService.kt
  4. 4
      app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt
  5. 37
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  6. 16
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceAdapter.kt
  7. 4
      app/src/main/java/io/legado/app/ui/rss/source/debug/RssSourceDebugModel.kt
  8. 4
      app/src/main/java/io/legado/app/web/SourceDebugWebSocket.kt
  9. 36
      app/src/main/res/layout/item_book_source.xml

@ -22,6 +22,7 @@ object EventBus {
const val UP_DOWNLOAD = "upDownload" const val UP_DOWNLOAD = "upDownload"
const val SAVE_CONTENT = "saveContent" const val SAVE_CONTENT = "saveContent"
const val CHECK_SOURCE = "checkSource" const val CHECK_SOURCE = "checkSource"
const val CHECK_SOURCE_MESSAGE = "checkSourceMessage"
const val CHECK_SOURCE_DONE = "checkSourceDone" const val CHECK_SOURCE_DONE = "checkSourceDone"
const val TIP_COLOR = "tipColor" const val TIP_COLOR = "tipColor"
const val SOURCE_CHANGED = "sourceChanged" const val SOURCE_CHANGED = "sourceChanged"

@ -1,10 +1,9 @@
package io.legado.app.model package io.legado.app.model
import android.annotation.SuppressLint import android.annotation.SuppressLint
import io.legado.app.data.entities.Book import android.util.Log
import io.legado.app.data.entities.BookChapter import io.legado.app.constant.EventBus
import io.legado.app.data.entities.RssArticle import io.legado.app.data.entities.*
import io.legado.app.data.entities.RssSource
import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.model.rss.Rss import io.legado.app.model.rss.Rss
import io.legado.app.model.webBook.WebBook import io.legado.app.model.webBook.WebBook
@ -12,13 +11,17 @@ import io.legado.app.utils.HtmlFormatter
import io.legado.app.utils.isAbsUrl import io.legado.app.utils.isAbsUrl
import io.legado.app.utils.msg import io.legado.app.utils.msg
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.flow
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.ArrayList
object Debug { object Debug {
var callback: Callback? = null var callback: Callback? = null
private var debugSource: String? = null private var debugSource: String? = null
private val tasks: CompositeCoroutine = CompositeCoroutine() private val tasks: CompositeCoroutine = CompositeCoroutine()
val debugMessageMap = ConcurrentHashMap<String, ArrayList<String>>()
@SuppressLint("ConstantLocale") @SuppressLint("ConstantLocale")
private val DEBUG_TIME_FORMAT = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault()) private val DEBUG_TIME_FORMAT = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault())
@ -44,6 +47,10 @@ object Debug {
printMsg = "$time $printMsg" printMsg = "$time $printMsg"
} }
it.printLog(state, printMsg) it.printLog(state, printMsg)
Log.d(EventBus.CHECK_SOURCE_MESSAGE, "debugMessage to filter $printMsg")
if (sourceUrl != null && printMsg.length < 30) {
debugMessageMap[sourceUrl]?.add(printMsg)
}
} }
} }
@ -61,6 +68,12 @@ object Debug {
} }
} }
fun startCheck(source: BookSource) {
debugSource = source.bookSourceUrl
startTime = System.currentTimeMillis()
debugMessageMap[source.bookSourceUrl] = arrayListOf()
}
fun startDebug(scope: CoroutineScope, rssSource: RssSource) { fun startDebug(scope: CoroutineScope, rssSource: RssSource) {
cancelDebug() cancelDebug()
debugSource = rssSource.sourceUrl debugSource = rssSource.sourceUrl
@ -246,6 +259,7 @@ object Debug {
interface Callback { interface Callback {
fun printLog(state: Int, msg: String) fun printLog(state: Int, msg: String)
fun printCheckSourceMessage(sourceUrl: String, msg: String)
} }
} }

@ -1,6 +1,7 @@
package io.legado.app.service package io.legado.app.service
import android.content.Intent import android.content.Intent
import android.util.Log
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseService import io.legado.app.base.BaseService
@ -12,6 +13,7 @@ import io.legado.app.data.entities.BookSource
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.IntentHelp import io.legado.app.help.IntentHelp
import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.model.Debug
import io.legado.app.model.webBook.WebBook import io.legado.app.model.webBook.WebBook
import io.legado.app.service.help.CheckSource import io.legado.app.service.help.CheckSource
import io.legado.app.ui.book.source.manage.BookSourceActivity import io.legado.app.ui.book.source.manage.BookSourceActivity
@ -29,6 +31,16 @@ class CheckSourceService : BaseService() {
private val checkedIds = ArrayList<String>() private val checkedIds = ArrayList<String>()
private var processIndex = 0 private var processIndex = 0
private var notificationMsg = "" private var notificationMsg = ""
private val debugCallback = object : Debug.Callback{
override fun printLog(state: Int, msg: String) {
}
@Synchronized
override fun printCheckSourceMessage(sourceUrl: String, msg: String) {
postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(sourceUrl, msg))
Log.d(EventBus.CHECK_SOURCE_MESSAGE, "printCheckSourceMessage to post $msg")
}
}
private val notificationBuilder by lazy { private val notificationBuilder by lazy {
NotificationCompat.Builder(this, AppConst.channelIdReadAloud) NotificationCompat.Builder(this, AppConst.channelIdReadAloud)
.setSmallIcon(R.drawable.ic_network_check) .setSmallIcon(R.drawable.ic_network_check)
@ -48,6 +60,7 @@ class CheckSourceService : BaseService() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
notificationMsg = getString(R.string.start) notificationMsg = getString(R.string.start)
Debug.callback = debugCallback
upNotification() upNotification()
} }
@ -65,6 +78,7 @@ class CheckSourceService : BaseService() {
super.onDestroy() super.onDestroy()
tasks.clear() tasks.clear()
searchCoroutine.close() searchCoroutine.close()
Debug.callback = null
postEvent(EventBus.CHECK_SOURCE_DONE, 0) postEvent(EventBus.CHECK_SOURCE_DONE, 0)
} }
@ -98,6 +112,7 @@ class CheckSourceService : BaseService() {
if (index < allIds.size) { if (index < allIds.size) {
val sourceUrl = allIds[index] val sourceUrl = allIds[index]
appDb.bookSourceDao.getBookSource(sourceUrl)?.let { source -> appDb.bookSourceDao.getBookSource(sourceUrl)?.let { source ->
Debug.startCheck(source)
check(source) check(source)
} ?: onNext(sourceUrl, "") } ?: onNext(sourceUrl, "")
} }
@ -145,6 +160,7 @@ class CheckSourceService : BaseService() {
}?.joinToString("\n") }?.joinToString("\n")
appDb.bookSourceDao.update(source) appDb.bookSourceDao.update(source)
}.onFinally(searchCoroutine) { }.onFinally(searchCoroutine) {
postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(source.bookSourceUrl, null))
onNext(source.bookSourceUrl, source.bookSourceName) onNext(source.bookSourceUrl, source.bookSourceName)
} }
} }

@ -51,6 +51,10 @@ class BookSourceDebugModel(application: Application) : BaseViewModel(application
} }
} }
override fun printCheckSourceMessage(sourceUrl: String, msg: String) {
TODO("Not yet implemented")
}
override fun onCleared() { override fun onCleared() {
super.onCleared() super.onCleared()
Debug.cancelDebug(true) Debug.cancelDebug(true)

@ -9,6 +9,7 @@ import android.view.SubMenu
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.os.bundleOf
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
@ -24,6 +25,7 @@ import io.legado.app.help.LocalConfig
import io.legado.app.lib.dialogs.alert import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.primaryTextColor import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.model.Debug
import io.legado.app.service.help.CheckSource import io.legado.app.service.help.CheckSource
import io.legado.app.ui.association.ImportBookSourceDialog import io.legado.app.ui.association.ImportBookSourceDialog
import io.legado.app.ui.book.source.debug.BookSourceDebugActivity import io.legado.app.ui.book.source.debug.BookSourceDebugActivity
@ -39,7 +41,8 @@ import io.legado.app.ui.widget.recycler.VerticalDivider
import io.legado.app.utils.* import io.legado.app.utils.*
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File
@ -337,6 +340,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
CheckSource.keyword = it CheckSource.keyword = it
} }
} }
adapter.notifyItemRangeChanged(0, adapter.itemCount, bundleOf(Pair("startChecking", null)))
CheckSource.start(this@BookSourceActivity, adapter.selection) CheckSource.start(this@BookSourceActivity, adapter.selection)
} }
noButton() noButton()
@ -424,6 +428,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
} }
override fun observeLiveBus() { override fun observeLiveBus() {
val checkSourceMessageFlow = flow<String> {}
observeEvent<String>(EventBus.CHECK_SOURCE) { msg -> observeEvent<String>(EventBus.CHECK_SOURCE) { msg ->
snackBar?.setText(msg) ?: let { snackBar?.setText(msg) ?: let {
snackBar = Snackbar snackBar = Snackbar
@ -434,14 +439,36 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
} }
} }
observeEvent<Int>(EventBus.CHECK_SOURCE_DONE) { observeEvent<Int>(EventBus.CHECK_SOURCE_DONE) {
adapter.notifyItemRangeChanged(0, adapter.itemCount, bundleOf(Pair("checkSourceDone", null)))
snackBar?.dismiss() snackBar?.dismiss()
snackBar = null snackBar = null
groups.map { group -> // groups.map { group ->
if (group.contains("失效")) { // if (group.contains("失效")) {
searchView.setQuery("失效", true) // searchView.setQuery("失效", true)
toastOnUi("发现有失效书源,已为您自动筛选!") // toastOnUi("发现有失效书源,已为您自动筛选!")
// }
// }
}
observeEvent<Pair<String, String>>(EventBus.CHECK_SOURCE_MESSAGE) { messagePair ->
sourceFlowJob?.cancel()
val messageFlow = Debug.debugMessageMap[messagePair.first]?.asFlow()
if (messageFlow != null) {
sourceFlowJob = launch {
var index: Int = -1
appDb.bookSourceDao.flowSearch(messagePair.first)
.map { adapter.getItems().indexOf(it[0]) }
.collect {
index = it }
if (index > -1){
messageFlow.onEach { delay(300L) }.buffer(10)
.collect { adapter.notifyItemChanged(index, bundleOf(Pair(EventBus.CHECK_SOURCE_MESSAGE, it))) }
}
} }
} }
} }
} }

@ -13,9 +13,11 @@ import androidx.recyclerview.widget.RecyclerView
import io.legado.app.R 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.constant.EventBus
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.databinding.ItemBookSourceBinding import io.legado.app.databinding.ItemBookSourceBinding
import io.legado.app.lib.theme.backgroundColor import io.legado.app.lib.theme.backgroundColor
import io.legado.app.model.Debug
import io.legado.app.ui.widget.recycler.DragSelectTouchHelper import io.legado.app.ui.widget.recycler.DragSelectTouchHelper
import io.legado.app.ui.widget.recycler.ItemTouchCallback.Callback import io.legado.app.ui.widget.recycler.ItemTouchCallback.Callback
import io.legado.app.utils.ColorUtils import io.legado.app.utils.ColorUtils
@ -107,17 +109,31 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
} }
swtEnabled.isChecked = item.enabled swtEnabled.isChecked = item.enabled
cbBookSource.isChecked = selected.contains(item) cbBookSource.isChecked = selected.contains(item)
ivDebugText.text = Debug.debugMessageMap[item.bookSourceUrl]?.lastOrNull() ?: ""
ivDebugText.visibility = if(ivDebugText.text.toString().length > 1) View.VISIBLE else View.GONE
upShowExplore(ivExplore, item) upShowExplore(ivExplore, item)
} else { } else {
payload.keySet().map { payload.keySet().map {
when (it) { when (it) {
"selected" -> cbBookSource.isChecked = selected.contains(item) "selected" -> cbBookSource.isChecked = selected.contains(item)
"startChecking" -> {
ivProgressBar.visibility = if(selected.contains(item)) View.VISIBLE else View.GONE
}
"checkSourceDone" -> {
ivProgressBar.visibility = if(selected.contains(item)) View.VISIBLE else ivProgressBar.visibility
}
EventBus.CHECK_SOURCE_MESSAGE -> {
ivDebugText.text = (payload[it] as? String) ?: ""
ivDebugText.visibility = if(ivDebugText.text.toString().length > 1) View.VISIBLE else View.GONE
}
} }
} }
} }
} }
} }
override fun registerListener(holder: ItemViewHolder, binding: ItemBookSourceBinding) { override fun registerListener(holder: ItemViewHolder, binding: ItemBookSourceBinding) {
binding.apply { binding.apply {
swtEnabled.setOnCheckedChangeListener { view, checked -> swtEnabled.setOnCheckedChangeListener { view, checked ->

@ -44,6 +44,10 @@ class RssSourceDebugModel(application: Application) : BaseViewModel(application)
} }
} }
override fun printCheckSourceMessage(sourceUrl: String, msg: String) {
TODO("Not yet implemented")
}
override fun onCleared() { override fun onCleared() {
super.onCleared() super.onCleared()
Debug.cancelDebug(true) Debug.cancelDebug(true)

@ -95,4 +95,8 @@ class SourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) :
} }
} }
override fun printCheckSourceMessage(sourceUrl: String, msg: String) {
TODO("Not yet implemented")
}
} }

@ -17,7 +17,7 @@
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/swt_enabled" app:layout_constraintRight_toLeftOf="@id/swt_enabled"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" /> app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" />
<io.legado.app.lib.theme.view.ATESwitch <io.legado.app.lib.theme.view.ATESwitch
android:id="@+id/swt_enabled" android:id="@+id/swt_enabled"
@ -29,7 +29,7 @@
tools:ignore="RtlSymmetry" tools:ignore="RtlSymmetry"
app:layout_constraintRight_toLeftOf="@id/iv_edit" app:layout_constraintRight_toLeftOf="@id/iv_edit"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" /> app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" />
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_edit" android:id="@+id/iv_edit"
@ -43,7 +43,7 @@
android:tint="@color/primaryText" android:tint="@color/primaryText"
app:layout_constraintRight_toLeftOf="@id/iv_menu_more" app:layout_constraintRight_toLeftOf="@id/iv_menu_more"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" /> app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" />
<androidx.appcompat.widget.AppCompatImageView <androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_menu_more" android:id="@+id/iv_menu_more"
@ -55,7 +55,7 @@
android:tint="@color/primaryText" android:tint="@color/primaryText"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toTopOf="@id/iv_progressBar"
tools:ignore="RtlHardcoded" /> tools:ignore="RtlHardcoded" />
<io.legado.app.ui.widget.image.CircleImageView <io.legado.app.ui.widget.image.CircleImageView
@ -68,4 +68,32 @@
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<io.legado.app.lib.theme.view.ATEProgressBar
android:id="@+id/iv_progressBar"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="start|center_vertical"
android:animationResolution="1000"
android:indeterminate="true"
android:visibility="gone"
android:indeterminateBehavior="repeat"
tools:visibility="visible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_menu_more"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@+id/iv_debug_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
tools:text="@string/debug_hint"
android:text=""
android:visibility="gone"
tools:visibility="visible"
android:layout_marginStart="10dp"
app:layout_constraintStart_toEndOf="@id/iv_progressBar"
app:layout_constraintTop_toTopOf="@id/iv_progressBar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
Loading…
Cancel
Save