pull/32/head
Administrator 5 years ago
parent 55857cce15
commit 24b22ea2e1
  1. 43
      app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt
  2. 50
      app/src/main/java/io/legado/app/help/EventMessage.kt
  3. 65
      app/src/main/java/io/legado/app/ui/sourcedebug/SourceDebugActivity.kt
  4. 31
      app/src/main/java/io/legado/app/ui/sourcedebug/SourceDebugAdapter.kt
  5. 51
      app/src/main/java/io/legado/app/ui/sourcedebug/SourceDebugModel.kt
  6. 2
      app/src/main/java/io/legado/app/ui/sourceedit/SourceEditActivity.kt

@ -53,11 +53,11 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context) : Rec
} }
fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegate(viewType: Int, delegate: DELEGATE) { fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegate(viewType: Int, delegate: DELEGATE) {
itemDelegates.put(viewType, delegate) itemDelegates[viewType] = delegate
} }
fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegate(delegate: DELEGATE) { fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegate(delegate: DELEGATE) {
itemDelegates.put(itemDelegates.size, delegate) itemDelegates[itemDelegates.size] = delegate
} }
fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegates(vararg delegates: DELEGATE) { fun <DELEGATE : ItemViewDelegate<ITEM>> addItemViewDelegates(vararg delegates: DELEGATE) {
@ -148,26 +148,15 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context) : Rec
synchronized(lock) { synchronized(lock) {
val oldSize = getActualItemCount() val oldSize = getActualItemCount()
if (this.items.add(item)) { if (this.items.add(item)) {
if (oldSize == 0) { notifyItemInserted(oldSize + getHeaderCount())
notifyDataSetChanged()
} else {
notifyItemInserted(oldSize + getHeaderCount())
}
} }
} }
} }
fun addItems(position: Int, newItems: List<ITEM>) { fun addItems(position: Int, newItems: List<ITEM>) {
synchronized(lock) { synchronized(lock) {
val oldSize = getActualItemCount() if (this.items.addAll(position, newItems)) {
if (position in 0 until oldSize) { notifyItemRangeInserted(position + getHeaderCount(), newItems.size)
if (if (oldSize == 0) this.items.addAll(newItems) else this.items.addAll(position, newItems)) {
if (oldSize == 0) {
notifyDataSetChanged()
} else {
notifyItemRangeChanged(position + getHeaderCount(), newItems.size)
}
}
} }
} }
} }
@ -176,33 +165,32 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context) : Rec
synchronized(lock) { synchronized(lock) {
val oldSize = getActualItemCount() val oldSize = getActualItemCount()
if (this.items.addAll(newItems)) { if (this.items.addAll(newItems)) {
if (oldSize == 0) { notifyItemRangeInserted(oldSize + getHeaderCount(), newItems.size)
notifyDataSetChanged()
} else {
notifyItemRangeChanged(oldSize + getHeaderCount(), newItems.size)
}
} }
} }
} }
fun removeItem(position: Int) { fun removeItem(position: Int) {
synchronized(lock) { synchronized(lock) {
if (this.items.removeAt(position) != null) if (this.items.removeAt(position) != null) {
notifyItemRemoved(position + getHeaderCount()) notifyItemRemoved(position + getHeaderCount())
}
} }
} }
fun removeItem(item: ITEM) { fun removeItem(item: ITEM) {
synchronized(lock) { synchronized(lock) {
if (this.items.remove(item)) if (this.items.remove(item)) {
notifyItemRemoved(this.items.indexOf(item) + getHeaderCount()) notifyItemRemoved(this.items.indexOf(item) + getHeaderCount())
}
} }
} }
fun removeItems(items: List<ITEM>) { fun removeItems(items: List<ITEM>) {
synchronized(lock) { synchronized(lock) {
if (this.items.removeAll(items)) if (this.items.removeAll(items)) {
notifyDataSetChanged() notifyDataSetChanged()
}
} }
} }
@ -234,6 +222,13 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context) : Rec
} }
} }
fun clearItems() {
synchronized(lock) {
this.items.clear()
notifyDataSetChanged()
}
}
fun isEmpty(): Boolean { fun isEmpty(): Boolean {
return items.isEmpty() return items.isEmpty()
} }

@ -0,0 +1,50 @@
package io.legado.app.help
import android.text.TextUtils
import java.util.Arrays
class EventMessage {
var what: Int?=null
var tag: String? = null
var obj: Any? = null
fun isFrom(tag: String): Boolean {
return TextUtils.equals(this.tag, tag)
}
fun maybeFrom(vararg tags: String): Boolean {
return listOf(*tags).contains(tag)
}
companion object {
fun obtain(tag: String): EventMessage {
val message = EventMessage()
message.tag = tag
return message
}
fun obtain(what: Int): EventMessage {
val message = EventMessage()
message.what = what
return message
}
fun obtain(what: Int, obj: Any): EventMessage {
val message = EventMessage()
message.what = what
message.obj = obj
return message
}
fun obtain(tag: String, obj: Any): EventMessage {
val message = EventMessage()
message.tag = tag
message.obj = obj
return message
}
}
}

@ -3,48 +3,43 @@ package io.legado.app.ui.sourcedebug
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.lib.theme.ATH import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.ThemeStore import io.legado.app.lib.theme.ThemeStore
import io.legado.app.model.WebBook
import io.legado.app.model.webbook.SourceDebug import io.legado.app.model.webbook.SourceDebug
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import io.legado.app.utils.isAbsUrl
import kotlinx.android.synthetic.main.activity_source_debug.* import kotlinx.android.synthetic.main.activity_source_debug.*
import kotlinx.android.synthetic.main.view_title_bar.* import kotlinx.android.synthetic.main.view_title_bar.*
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.launch
import org.jetbrains.anko.toast import org.jetbrains.anko.toast
class SourceDebugActivity : BaseActivity<AndroidViewModel>(), SourceDebug.Callback { class SourceDebugActivity : BaseActivity<SourceDebugModel>() {
override val viewModel: AndroidViewModel override val viewModel: SourceDebugModel
get() = getViewModel(AndroidViewModel::class.java) get() = getViewModel(SourceDebugModel::class.java)
override val layoutID: Int override val layoutID: Int
get() = R.layout.activity_source_debug get() = R.layout.activity_source_debug
private lateinit var adapter: SourceDebugAdapter private lateinit var adapter: SourceDebugAdapter
private var bookSource: BookSource? = null
override fun onActivityCreated(viewModel: AndroidViewModel, savedInstanceState: Bundle?) { override fun onActivityCreated(viewModel: SourceDebugModel, savedInstanceState: Bundle?) {
launch(IO) { viewModel.init(intent.getStringExtra("key"))
intent.getStringExtra("key")?.let {
bookSource = App.db.bookSourceDao().findByKey(it)
}
}
initRecyclerView() initRecyclerView()
initSearchView() initSearchView()
viewModel.logs.observe(this, Observer {
adapter.addItem(it.obj as String)
if (it.what == -1 || it.what == 1000) {
rotate_loading.hide()
}
})
} }
private fun initRecyclerView() { private fun initRecyclerView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(recycler_view)
adapter = SourceDebugAdapter() adapter = SourceDebugAdapter(this)
recycler_view.layoutManager = LinearLayoutManager(this) recycler_view.layoutManager = LinearLayoutManager(this)
recycler_view.adapter = adapter recycler_view.adapter = adapter
rotate_loading.loadingColor = ThemeStore.accentColor(this) rotate_loading.loadingColor = ThemeStore.accentColor(this)
@ -69,36 +64,12 @@ class SourceDebugActivity : BaseActivity<AndroidViewModel>(), SourceDebug.Callba
} }
private fun startSearch(key: String) { private fun startSearch(key: String) {
adapter.logList.clear() adapter.clearItems()
adapter.notifyDataSetChanged() viewModel.startDebug(key, {
bookSource?.let {
SourceDebug.debugSource = it.bookSourceUrl
rotate_loading.show() rotate_loading.show()
if (key.isAbsUrl()) { }, {
val book = Book() toast("未获取到书源")
book.origin = it.bookSourceUrl })
book.bookUrl = key
SourceDebug.printLog(it.bookSourceUrl, 1, "开始访问$key")
SourceDebug(WebBook(it), this)
.infoDebug(book)
} else {
SourceDebug.printLog(it.bookSourceUrl, 1, "开始搜索关键字$key")
SourceDebug(WebBook(it), this)
.searchDebug(key)
}
} ?: toast("未获取到书源")
}
override fun printLog(state: Int, msg: String) {
launch {
synchronized(this) {
adapter.logList.add(msg)
adapter.notifyItemChanged(adapter.logList.size - 1)
if (state == -1 || state == 1000) {
rotate_loading.hide()
}
}
}
} }
override fun onDestroy() { override fun onDestroy() {

@ -1,32 +1,15 @@
package io.legado.app.ui.sourcedebug package io.legado.app.ui.sourcedebug
import android.view.LayoutInflater import android.content.Context
import android.view.View
import android.view.ViewGroup
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.SimpleRecyclerAdapter
import kotlinx.android.synthetic.main.item_source_debug.view.* import kotlinx.android.synthetic.main.item_source_debug.view.*
class SourceDebugAdapter : RecyclerView.Adapter<SourceDebugAdapter.MyViewHolder>() { class SourceDebugAdapter(context: Context) : SimpleRecyclerAdapter<String>(context, R.layout.item_source_debug) {
override fun convert(holder: ItemViewHolder, item: String, payloads: MutableList<Any>) {
val logList = arrayListOf<String>() holder.itemView.apply {
text_view.text = item
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
return MyViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_source_debug, parent, false))
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(logList[position])
}
override fun getItemCount(): Int {
return logList.size
}
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(log: String) = with(itemView) {
text_view.text = log
} }
} }
} }

@ -0,0 +1,51 @@
package io.legado.app.ui.sourcedebug
import android.app.Application
import androidx.lifecycle.MutableLiveData
import io.legado.app.App
import io.legado.app.base.BaseViewModel
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookSource
import io.legado.app.help.EventMessage
import io.legado.app.model.WebBook
import io.legado.app.model.webbook.SourceDebug
import io.legado.app.utils.isAbsUrl
class SourceDebugModel(application: Application) : BaseViewModel(application), SourceDebug.Callback {
val logs: MutableLiveData<EventMessage> = MutableLiveData()
private var bookSource: BookSource? = null
fun init(sourceUrl: String?) {
sourceUrl?.let {
//优先使用这个,不会抛出异常
execute {
bookSource = App.db.bookSourceDao().findByKey(sourceUrl)
}
}
}
fun startDebug(key: String, start: (() -> Unit)? = null, error: (() -> Unit)? = null) {
bookSource?.let {
start?.let { it() }
SourceDebug.debugSource = it.bookSourceUrl
if (key.isAbsUrl()) {
val book = Book()
book.origin = it.bookSourceUrl
book.bookUrl = key
SourceDebug.printLog(it.bookSourceUrl, 1, "开始访问$key")
SourceDebug(WebBook(it), this)
.infoDebug(book)
} else {
SourceDebug.printLog(it.bookSourceUrl, 1, "开始搜索关键字$key")
SourceDebug(WebBook(it), this)
.searchDebug(key)
}
} ?: error?.let { it() }
}
override fun printLog(state: Int, msg: String) {
logs.postValue(EventMessage.obtain(state, msg))
}
}

@ -81,7 +81,7 @@ class SourceEditActivity : BaseActivity<SourceEditViewModel>(false), KeyboardToo
toast("书源名称和URL不能为空") toast("书源名称和URL不能为空")
} else { } else {
viewModel.save(bookSource) { viewModel.save(bookSource) {
startActivity<SourceDebugActivity>(Pair("key", bookSource.bookSourceUrl)) startActivity<SourceDebugActivity>("key" to bookSource.bookSourceUrl)
} }
} }
} }

Loading…
Cancel
Save