mirror of
https://gitee.com/zhangsken/AndroidIDE.git
synced 2026-10-16 15:56:48 +08:00
Fixed lag when searching in tasks
This commit is contained in:
Binary file not shown.
@@ -17,10 +17,14 @@
|
||||
|
||||
package com.itsaky.androidide.adapters
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.DiffUtil.Callback
|
||||
import androidx.recyclerview.widget.DiffUtil.DiffResult
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.blankj.utilcode.util.ThreadUtils
|
||||
import com.itsaky.androidide.progress.ProcessCancelledException
|
||||
import com.itsaky.androidide.progress.ProgressManager
|
||||
import com.itsaky.androidide.utils.StopWatch
|
||||
|
||||
/**
|
||||
* Filterable [RecyclerView.Adapter].
|
||||
@@ -38,20 +42,20 @@ abstract class FilterableRecyclerViewAdapter<V : RecyclerView.ViewHolder, D>(val
|
||||
*
|
||||
* @param query The query.
|
||||
*/
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
fun filter(query: String?) {
|
||||
filterThread?.let { ProgressManager.instance.cancel(it) }
|
||||
filterThread =
|
||||
FilterThread(this.items, query?.trim(), this::onFilter).apply {
|
||||
start()
|
||||
join()
|
||||
FilterThread(this.items, query?.trim(), this::onFilter) { filtered, result ->
|
||||
if (result == null) {
|
||||
this.filtered = this.items
|
||||
notifyDataSetChanged()
|
||||
return@FilterThread
|
||||
}
|
||||
this.filtered = filtered
|
||||
result.dispatchUpdatesTo(this)
|
||||
}
|
||||
|
||||
filterThread!!.let {
|
||||
ThreadUtils.runOnUiThread {
|
||||
this.filtered = it.filtered
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
filterThread?.start()
|
||||
}
|
||||
|
||||
/** Get the list item at given index. */
|
||||
@@ -74,20 +78,61 @@ abstract class FilterableRecyclerViewAdapter<V : RecyclerView.ViewHolder, D>(val
|
||||
private class FilterThread<E>(
|
||||
val items: List<E>,
|
||||
val query: String?,
|
||||
val onFilter: (E, String) -> Boolean
|
||||
val onFilter: (E, String) -> Boolean,
|
||||
val onFiltered: (List<E>, DiffResult?) -> Unit
|
||||
) : Thread("TaskFilterThread") {
|
||||
|
||||
lateinit var filtered: List<E>
|
||||
|
||||
override fun run() {
|
||||
this.filtered =
|
||||
if (query.isNullOrBlank()) {
|
||||
items
|
||||
} else
|
||||
items.filter {
|
||||
ProgressManager.abortIfCancelled()
|
||||
onFilter(it, query)
|
||||
try {
|
||||
doFilter()
|
||||
} catch (e: ProcessCancelledException) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private fun doFilter() {
|
||||
if (query.isNullOrBlank()) {
|
||||
postFilter(items, null)
|
||||
return
|
||||
}
|
||||
|
||||
val filtered = items.filter {
|
||||
ProgressManager.abortIfCancelled()
|
||||
onFilter(it, query)
|
||||
}
|
||||
|
||||
val result =
|
||||
DiffUtil.calculateDiff(
|
||||
object : Callback() {
|
||||
override fun getOldListSize(): Int {
|
||||
ProgressManager.abortIfCancelled()
|
||||
return items.size
|
||||
}
|
||||
|
||||
override fun getNewListSize(): Int {
|
||||
ProgressManager.abortIfCancelled()
|
||||
return filtered.size
|
||||
}
|
||||
|
||||
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
ProgressManager.abortIfCancelled()
|
||||
return items[oldItemPosition] == filtered[newItemPosition]
|
||||
}
|
||||
|
||||
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
|
||||
ProgressManager.abortIfCancelled()
|
||||
return items[oldItemPosition] == filtered[newItemPosition]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
postFilter(filtered, result)
|
||||
}
|
||||
|
||||
private fun postFilter(filtered: List<E>, result: DiffResult?) {
|
||||
ThreadUtils.runOnUiThread {
|
||||
onFiltered(filtered, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package com.itsaky.androidide.fragments
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.text.Editable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -25,6 +26,7 @@ import android.view.ViewGroup
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.transition.TransitionManager
|
||||
import com.blankj.utilcode.util.ThreadUtils
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.transition.MaterialSharedAxis
|
||||
import com.itsaky.androidide.R.string
|
||||
@@ -68,7 +70,7 @@ class RunTasksDialogFragment : BottomSheetDialogFragment() {
|
||||
// The minimum amount of time (in milliseconds) the adapter should wait after the query is
|
||||
// changed before starting any further filter request.
|
||||
// A too less value here will result in UI lags
|
||||
private const val SEARCH_DELAY = 500
|
||||
private const val SEARCH_DELAY = 500L
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
@@ -95,7 +97,6 @@ class RunTasksDialogFragment : BottomSheetDialogFragment() {
|
||||
if (adapter !is RunTasksCategoryAdapter) {
|
||||
return@observeQuery
|
||||
}
|
||||
|
||||
for (index in 0 until viewModel.categories.size) {
|
||||
val layout =
|
||||
run.categories.layoutManager
|
||||
@@ -112,8 +113,12 @@ class RunTasksDialogFragment : BottomSheetDialogFragment() {
|
||||
|
||||
run.searchInput.editText?.addTextChangedListener(
|
||||
object : SingleTextWatcher() {
|
||||
val searchRunner = Runnable {
|
||||
viewModel.query = run.searchInput.editText?.text?.toString() ?: ""
|
||||
}
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
viewModel.query = s?.toString() ?: ""
|
||||
ThreadUtils.getMainHandler().removeCallbacks(searchRunner)
|
||||
ThreadUtils.runOnUiThreadDelayed(searchRunner, SEARCH_DELAY)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -50,7 +50,7 @@ class ProgressManager private constructor(){
|
||||
|
||||
@JvmName("internalAbortIfCancelled")
|
||||
private fun abortIfCancelled() {
|
||||
val checker = threads[Thread.currentThread()]
|
||||
val checker = threads.remove(Thread.currentThread())
|
||||
if (checker != null && checker.isCancelled()) {
|
||||
throw ProcessCancelledException()
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user