try to use flow

pull/1251/head
Jason Yao 3 years ago
parent bffc6d6e4a
commit d2bd237772
  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 SAVE_CONTENT = "saveContent"
const val CHECK_SOURCE = "checkSource"
const val CHECK_SOURCE_MESSAGE = "checkSourceMessage"
const val CHECK_SOURCE_DONE = "checkSourceDone"
const val TIP_COLOR = "tipColor"
const val SOURCE_CHANGED = "sourceChanged"

@ -1,10 +1,9 @@
package io.legado.app.model
import android.annotation.SuppressLint
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.RssArticle
import io.legado.app.data.entities.RssSource
import android.util.Log
import io.legado.app.constant.EventBus
import io.legado.app.data.entities.*
import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.model.rss.Rss
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.msg
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.flow
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.ArrayList
object Debug {
var callback: Callback? = null
private var debugSource: String? = null
private val tasks: CompositeCoroutine = CompositeCoroutine()
val debugMessageMap = ConcurrentHashMap<String, ArrayList<String>>()
@SuppressLint("ConstantLocale")
private val DEBUG_TIME_FORMAT = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault())
@ -44,6 +47,10 @@ object Debug {
printMsg = "$time $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) {
cancelDebug()
debugSource = rssSource.sourceUrl
@ -246,6 +259,7 @@ object Debug {
interface Callback {
fun printLog(state: Int, msg: String)
fun printCheckSourceMessage(sourceUrl: String, msg: String)
}
}

@ -1,6 +1,7 @@
package io.legado.app.service
import android.content.Intent
import android.util.Log
import androidx.core.app.NotificationCompat
import io.legado.app.R
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.IntentHelp
import io.legado.app.help.coroutine.CompositeCoroutine
import io.legado.app.model.Debug
import io.legado.app.model.webBook.WebBook
import io.legado.app.service.help.CheckSource
import io.legado.app.ui.book.source.manage.BookSourceActivity
@ -29,6 +31,16 @@ class CheckSourceService : BaseService() {
private val checkedIds = ArrayList<String>()
private var processIndex = 0
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 {
NotificationCompat.Builder(this, AppConst.channelIdReadAloud)
.setSmallIcon(R.drawable.ic_network_check)
@ -48,6 +60,7 @@ class CheckSourceService : BaseService() {
override fun onCreate() {
super.onCreate()
notificationMsg = getString(R.string.start)
Debug.callback = debugCallback
upNotification()
}
@ -65,6 +78,7 @@ class CheckSourceService : BaseService() {
super.onDestroy()
tasks.clear()
searchCoroutine.close()
Debug.callback = null
postEvent(EventBus.CHECK_SOURCE_DONE, 0)
}
@ -98,6 +112,7 @@ class CheckSourceService : BaseService() {
if (index < allIds.size) {
val sourceUrl = allIds[index]
appDb.bookSourceDao.getBookSource(sourceUrl)?.let { source ->
Debug.startCheck(source)
check(source)
} ?: onNext(sourceUrl, "")
}
@ -145,6 +160,7 @@ class CheckSourceService : BaseService() {
}?.joinToString("\n")
appDb.bookSourceDao.update(source)
}.onFinally(searchCoroutine) {
postEvent(EventBus.CHECK_SOURCE_MESSAGE, Pair(source.bookSourceUrl, null))
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() {
super.onCleared()
Debug.cancelDebug(true)

@ -9,6 +9,7 @@ import android.view.SubMenu
import androidx.activity.viewModels
import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.SearchView
import androidx.core.os.bundleOf
import androidx.documentfile.provider.DocumentFile
import androidx.recyclerview.widget.ItemTouchHelper
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.theme.ATH
import io.legado.app.lib.theme.primaryTextColor
import io.legado.app.model.Debug
import io.legado.app.service.help.CheckSource
import io.legado.app.ui.association.ImportBookSourceDialog
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.viewbindingdelegate.viewBinding
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import java.io.File
@ -337,6 +340,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
CheckSource.keyword = it
}
}
adapter.notifyItemRangeChanged(0, adapter.itemCount, bundleOf(Pair("startChecking", null)))
CheckSource.start(this@BookSourceActivity, adapter.selection)
}
noButton()
@ -424,6 +428,7 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
}
override fun observeLiveBus() {
val checkSourceMessageFlow = flow<String> {}
observeEvent<String>(EventBus.CHECK_SOURCE) { msg ->
snackBar?.setText(msg) ?: let {
snackBar = Snackbar
@ -434,14 +439,36 @@ class BookSourceActivity : VMBaseActivity<ActivityBookSourceBinding, BookSourceV
}
}
observeEvent<Int>(EventBus.CHECK_SOURCE_DONE) {
adapter.notifyItemRangeChanged(0, adapter.itemCount, bundleOf(Pair("checkSourceDone", null)))
snackBar?.dismiss()
snackBar = null
groups.map { group ->
if (group.contains("失效")) {
searchView.setQuery("失效", true)
toastOnUi("发现有失效书源,已为您自动筛选!")
// groups.map { group ->
// if (group.contains("失效")) {
// searchView.setQuery("失效", true)
// 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.base.adapter.ItemViewHolder
import io.legado.app.base.adapter.RecyclerAdapter
import io.legado.app.constant.EventBus
import io.legado.app.data.entities.BookSource
import io.legado.app.databinding.ItemBookSourceBinding
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.ItemTouchCallback.Callback
import io.legado.app.utils.ColorUtils
@ -107,16 +109,30 @@ class BookSourceAdapter(context: Context, val callBack: CallBack) :
}
swtEnabled.isChecked = item.enabled
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)
} else {
payload.keySet().map {
when (it) {
"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) {
binding.apply {

@ -44,6 +44,10 @@ class RssSourceDebugModel(application: Application) : BaseViewModel(application)
}
}
override fun printCheckSourceMessage(sourceUrl: String, msg: String) {
TODO("Not yet implemented")
}
override fun onCleared() {
super.onCleared()
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_constraintRight_toLeftOf="@id/swt_enabled"
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
android:id="@+id/swt_enabled"
@ -29,7 +29,7 @@
tools:ignore="RtlSymmetry"
app:layout_constraintRight_toLeftOf="@id/iv_edit"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_edit"
@ -43,7 +43,7 @@
android:tint="@color/primaryText"
app:layout_constraintRight_toLeftOf="@id/iv_menu_more"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
app:layout_constraintBottom_toBottomOf="@id/iv_menu_more" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_menu_more"
@ -55,7 +55,7 @@
android:tint="@color/primaryText"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/iv_progressBar"
tools:ignore="RtlHardcoded" />
<io.legado.app.ui.widget.image.CircleImageView
@ -68,4 +68,32 @@
app:layout_constraintRight_toRightOf="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>
Loading…
Cancel
Save