Merge remote-tracking branch 'origin/master'

pull/32/head
kunfei 5 years ago
commit 10abf12674
  1. 17
      app/src/main/java/io/legado/app/base/adapter/CommonRecyclerAdapter.kt
  2. 2
      app/src/main/java/io/legado/app/base/adapter/ItemViewDelegate.kt
  3. 23
      app/src/main/java/io/legado/app/help/coroutine/Coroutine.kt
  4. 3
      app/src/main/java/io/legado/app/model/WebBook.kt
  5. 59
      app/src/main/java/io/legado/app/model/webbook/SourceDebug.kt
  6. 136
      app/src/main/java/io/legado/app/ui/search/SearchViewModel.kt
  7. 7
      app/src/main/java/io/legado/app/ui/sourcedebug/SourceDebugActivity.kt
  8. 33
      app/src/main/java/io/legado/app/ui/sourcedebug/SourceDebugModel.kt

@ -198,8 +198,21 @@ abstract class CommonRecyclerAdapter<ITEM>(protected val context: Context) : Rec
synchronized(lock) {
val size = getActualItemCount()
if (oldPosition in 0 until size && newPosition in 0 until size) {
Collections.swap(this.items, oldPosition + getHeaderCount(), newPosition + getHeaderCount())
notifyDataSetChanged()
val srcPosition = oldPosition + getHeaderCount()
val targetPosition = newPosition + getHeaderCount()
Collections.swap(this.items, srcPosition, targetPosition)
notifyItemChanged(srcPosition)
notifyItemChanged(targetPosition)
}
}
}
fun updateItem(item: ITEM) {
synchronized(lock) {
val index = this.items.indexOf(item)
if (index >= 0) {
this.items[index] = item
notifyItemChanged(index)
}
}
}

@ -7,7 +7,7 @@ import android.content.Context
*
* item代理
*/
abstract class ItemViewDelegate<in ITEM>(protected val context: Context, val layoutId: Int) {
abstract class ItemViewDelegate<ITEM>(protected val context: Context, val layoutId: Int) {
abstract fun convert(holder: ItemViewHolder, item: ITEM, payloads: MutableList<Any>)

@ -30,6 +30,15 @@ class Coroutine<T>() {
private var errorReturn: Result<T>? = null
val isCancelled: Boolean
get() = job?.isCancelled ?: false
val isActive: Boolean
get() = job?.isActive ?: false
val isCompleted: Boolean
get() = job?.isCompleted ?: false
private constructor(
scope: CoroutineScope,
block: suspend CoroutineScope.() -> T
@ -106,24 +115,24 @@ class Coroutine<T>() {
private suspend fun executeInternal(block: suspend CoroutineScope.() -> T) {
tryCatch(
{
start?.let { it() }
start?.invoke(this)
val result = executeBlock(block, timeMillis ?: 0L)
success?.let { it(result) }
success?.invoke(this, result)
},
{ e ->
val consume: Boolean = errorReturn?.value?.let { value ->
success?.let { it(value) }
success?.invoke(this, value)
true
} ?: false
if (!consume) {
error?.let { it(e) }
error?.invoke(this, e)
}
},
{
finally?.let { it() }
finally?.invoke(this)
})
}
@ -142,9 +151,9 @@ class Coroutine<T>() {
try {
coroutineScope { tryBlock() }
} catch (e: Throwable) {
coroutineScope { errorBlock?.let { it(e) } }
coroutineScope { errorBlock?.invoke(this, e) }
} finally {
coroutineScope { finallyBlock?.let { it() } }
coroutineScope { finallyBlock?.invoke(this) }
}
}

@ -13,6 +13,9 @@ import io.legado.app.model.webbook.BookList
class WebBook(private val bookSource: BookSource) {
val sourceUrl: String
get() = bookSource.bookSourceUrl
fun searchBook(key: String, page: Int?, isSearch: Boolean = true): Coroutine<List<SearchBook>> {
return Coroutine.async {
bookSource.getSearchRule().searchUrl?.let { searchUrl ->

@ -4,23 +4,26 @@ import android.annotation.SuppressLint
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.help.BookHelp
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.WebBook
import io.legado.app.utils.htmlFormat
import io.legado.app.utils.isAbsUrl
import java.text.SimpleDateFormat
import java.util.*
class SourceDebug(private val webBook: WebBook, callback: Callback) {
companion object {
var debugSource: String? = null
var callback: Callback? = null
private var debugSource: String? = null
private var callback: Callback? = null
private val tasks: MutableList<Coroutine<*>> = mutableListOf()
@SuppressLint("ConstantLocale")
private val DEBUG_TIME_FORMAT = SimpleDateFormat("[mm:ss.SSS]", Locale.getDefault())
private val startTime: Long = System.currentTimeMillis()
fun printLog(sourceUrl: String?, state: Int, msg: String, print: Boolean = true, isHtml: Boolean = false) {
if (debugSource != sourceUrl) return
if (!print) return
if (debugSource != sourceUrl || callback == null || !print) return
var printMsg = msg
if (isHtml) {
printMsg = printMsg.htmlFormat()
@ -29,18 +32,46 @@ class SourceDebug(private val webBook: WebBook, callback: Callback) {
String.format("%s %s", DEBUG_TIME_FORMAT.format(Date(System.currentTimeMillis() - startTime)), printMsg)
callback?.printLog(state, printMsg)
}
fun cancelDebug(destroy: Boolean = false) {
tasks.forEach {
if (!it.isCancelled) {
it.cancel()
}
}
tasks.clear()
if (destroy) {
debugSource = null
callback = null
}
}
interface Callback {
fun printLog(state: Int, msg: String)
}
init {
debugSource = webBook.sourceUrl
SourceDebug.callback = callback
}
fun startDebug(key: String) {
cancelDebug()
with(webBook) {
if (key.isAbsUrl()) {
val book = Book()
book.origin = sourceUrl
book.bookUrl = key
printLog(sourceUrl, 1, "开始访问$key")
infoDebug(book)
} else {
printLog(sourceUrl, 1, "开始搜索关键字$key")
searchDebug(key)
}
}
}
fun searchDebug(key: String) {
webBook.searchBook(key, 1)
val search = webBook.searchBook(key, 1)
.onSuccess { searchBooks ->
searchBooks?.let {
if (searchBooks.isNotEmpty()) {
@ -51,20 +82,22 @@ class SourceDebug(private val webBook: WebBook, callback: Callback) {
.onError {
printLog(debugSource, -1, it.localizedMessage)
}
tasks.add(search)
}
fun infoDebug(book: Book) {
webBook.getBookInfo(book)
val info = webBook.getBookInfo(book)
.onSuccess {
tocDebug(book)
}
.onError {
printLog(debugSource, -1, it.localizedMessage)
}
tasks.add(info)
}
private fun tocDebug(book: Book) {
webBook.getChapterList(book)
val chapterList = webBook.getChapterList(book)
.onSuccess { chapterList ->
chapterList?.let {
if (it.isNotEmpty()) {
@ -75,10 +108,11 @@ class SourceDebug(private val webBook: WebBook, callback: Callback) {
.onError {
printLog(debugSource, -1, it.localizedMessage)
}
tasks.add(chapterList)
}
private fun contentDebug(book: Book, bookChapter: BookChapter) {
webBook.getContent(book, bookChapter)
val content = webBook.getContent(book, bookChapter)
.onSuccess { content ->
content?.let {
printLog(debugSource, 1000, it)
@ -87,6 +121,11 @@ class SourceDebug(private val webBook: WebBook, callback: Callback) {
.onError {
printLog(debugSource, -1, it.localizedMessage)
}
tasks.add(content)
}
interface Callback {
fun printLog(state: Int, msg: String)
}
fun printLog(

@ -10,6 +10,8 @@ import io.legado.app.data.entities.SearchBook
import io.legado.app.help.http.HttpHelper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class SearchViewModel(application: Application) : BaseViewModel(application) {
@ -19,86 +21,68 @@ class SearchViewModel(application: Application) : BaseViewModel(application) {
private val channel = Channel<Int>()//协程之间通信
fun search(start: (() -> Unit)? = null, finally: (() -> Unit)? = null) {
// launch {
// repeat(1000) {
// channel.send(it)
// }
// }
//
//
// val c = execute {
//
// Log.e("TAG1", "start")
//
// val response: String = HttpHelper.getApiService<CommonHttpApi>(
// "http://www.baidu.com"
// ).get("http://www.baidu.com").await()
//
// Log.e("TAG1", "result: $response")
//
// delay(2000L)
//
// response
// }
// .onStart {
// Log.e("TAG!", "start")
// start?.let { it() }
// }
launch {
repeat(1000) {
channel.send(it)
}
}
val c = execute {
val response: String = HttpHelper.getApiService<CommonHttpApi>(
"http://www.baidu.com"
).get("http://www.baidu.com").await()
delay(2000L)
response
}
.onStart {
Log.e("TAG!", "start")
start?.let { it() }
}
.onSuccess {
Log.e("TAG!", "success: $it")
}
.onError {
Log.e("TAG!", "error: $it")
}
.onFinally {
Log.e("TAG!", "finally")
if (finally != null) {
finally()
}
}
val c2 = plus(c)
// .timeout { 100L }
// .onErrorReturn { "error return2" }
.onStart {
//会拦截掉c的onStart
Log.e("TAG!", "start2")
start?.let { it() }
}
// .onSuccess {
// Log.e("TAG!", "success: $it")
// }
// .onError {
// Log.e("TAG!", "error: $it")
// }
// .onFinally {
// Log.e("TAG!", "finally")
// if (finally != null) {
// finally()
// }
// }
//
// val c2 = plus(c)
//// .timeout { 100L }
//// .onErrorReturn { "error return2" }
// .onStart {
// //会拦截掉c的onStart
// Log.e("TAG!", "start2")
// start?.let { it() }
// }
//// .onSuccess {
//// Log.e("TAG!", "success2: $it")
//// }
// .onError {
// Log.e("TAG!", "error2: $it")
// Log.e("TAG!", "success2: $it")
// }
// .onFinally {
// Log.e("TAG!", "finally2")
// if (finally != null) {
// finally()
// }
//
// Log.e("TAG!", "rec2: " + channel.receive())
// }
//
// launch {
// delay(1500L)
//// c2.cancel()
//
//// c.cancel()
// }
//
//
// launch {
// val list = test()
// println("size: ${list.size} $list")
// }
.onError {
Log.e("TAG!", "error2: $it")
}
.onFinally {
Log.e("TAG!", "finally2")
if (finally != null) {
finally()
}
execute {
test(this)
}.onSuccess {
println("size: ${it?.size} $it")
Log.e("TAG!", "rec2: " + channel.receive())
}
// execute {
// test(this)
// }.onSuccess {
// println("size: ${it?.size} $it")
// }
}
suspend fun test(scope: CoroutineScope): MutableList<String> {

@ -7,10 +7,8 @@ import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.R
import io.legado.app.base.BaseActivity
import io.legado.app.data.entities.BookSource
import io.legado.app.lib.theme.ATH
import io.legado.app.lib.theme.ThemeStore
import io.legado.app.model.webbook.SourceDebug
import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_source_debug.*
import kotlinx.android.synthetic.main.view_title_bar.*
@ -71,9 +69,4 @@ class SourceDebugActivity : BaseActivity<SourceDebugModel>() {
toast("未获取到书源")
})
}
override fun onDestroy() {
SourceDebug.debugSource = null
super.onDestroy()
}
}

@ -4,48 +4,39 @@ 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
private var webBook: WebBook? = null
fun init(sourceUrl: String?) {
sourceUrl?.let {
//优先使用这个,不会抛出异常
execute {
bookSource = App.db.bookSourceDao().findByKey(sourceUrl)
val bookSource = App.db.bookSourceDao().findByKey(sourceUrl)
bookSource?.let { webBook = WebBook(it) }
}
}
}
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(WebBook(it), this)
.printLog(it.bookSourceUrl, 1, "开始访问$key")
.infoDebug(book)
} else {
SourceDebug(WebBook(it), this)
.printLog(it.bookSourceUrl, 1, "开始搜索关键字$key")
.searchDebug(key)
}
} ?: error?.let { it() }
webBook?.let {
start?.invoke()
SourceDebug(it, this).startDebug(key)
} ?: error?.invoke()
}
override fun printLog(state: Int, msg: String) {
logs.postValue(EventMessage.obtain(state, msg))
}
override fun onCleared() {
super.onCleared()
SourceDebug.cancelDebug(true)
}
}

Loading…
Cancel
Save