Use coroutines for search

pull/1715/head
Alex Baker 3 years ago
parent 8181d20ff5
commit da967afaf5

@ -41,13 +41,8 @@ import com.todoroo.astrid.service.*
import com.todoroo.astrid.timers.TimerPlugin
import com.todoroo.astrid.utility.Flags
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.tasks.LocalBroadcastManager
import org.tasks.R
import org.tasks.ShortcutManager
@ -82,7 +77,6 @@ import timber.log.Timber
import java.text.ParseException
import java.time.format.FormatStyle
import java.util.*
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.max
@ -126,8 +120,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
private lateinit var taskAdapter: TaskAdapter
private var recyclerAdapter: TaskListRecyclerAdapter? = null
private lateinit var filter: Filter
private val searchSubject = PublishSubject.create<String>()
private var searchDisposable: Disposable? = null
private var searchJob: Job? = null
private lateinit var search: MenuItem
private var searchQuery: String? = null
private var mode: ActionMode? = null
@ -287,13 +280,17 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
}
private fun searchByQuery(query: String?) {
searchQuery = query?.trim { it <= ' ' } ?: ""
if (searchQuery?.isEmpty() == true) {
listViewModel.searchByFilter(
searchJob?.cancel()
searchJob = lifecycleScope.launch {
delay(SEARCH_DEBOUNCE_TIMEOUT)
searchQuery = query?.trim { it <= ' ' } ?: ""
if (searchQuery?.isEmpty() == true) {
listViewModel.searchByFilter(
BuiltInFilterExposer.getMyTasksFilter(requireContext().resources))
} else {
val savedFilter = createSearchFilter(searchQuery!!)
listViewModel.searchByFilter(savedFilter)
} else {
val savedFilter = createSearchFilter(searchQuery!!)
listViewModel.searchByFilter(savedFilter)
}
}
}
@ -465,13 +462,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
localBroadcastManager.unregisterReceiver(refreshReceiver)
}
override fun onDestroyView() {
super.onDestroyView()
if (searchDisposable != null && !searchDisposable!!.isDisposed) {
searchDisposable!!.dispose()
}
}
fun collapseSearchView(): Boolean {
return (search.isActionViewExpanded
&& (search.collapseActionView() || !search.isActionViewExpanded))
@ -569,10 +559,6 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
}
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
searchDisposable = searchSubject
.debounce(SEARCH_DEBOUNCE_TIMEOUT.toLong(), TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { query: String? -> searchByQuery(query) }
if (searchQuery == null) {
searchByQuery("")
}
@ -585,7 +571,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
listViewModel.searchByFilter(filter)
searchDisposable?.dispose()
searchJob?.cancel()
searchQuery = null
setupMenu()
return true
@ -598,7 +584,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
}
override fun onQueryTextChange(query: String): Boolean {
searchSubject.onNext(query)
searchByQuery(query)
return true
}
@ -890,7 +876,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL
private const val REQUEST_LIST_SETTINGS = 10101
private const val REQUEST_MOVE_TASKS = 10103
private const val REQUEST_TAG_TASKS = 10106
private const val SEARCH_DEBOUNCE_TIMEOUT = 300
private const val SEARCH_DEBOUNCE_TIMEOUT = 300L
fun newTaskListFragment(context: Context, filter: Filter?): TaskListFragment {
val fragment = TaskListFragment()
val bundle = Bundle()

@ -12,7 +12,6 @@ import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.Toolbar
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.widget.ContentLoadingProgressBar
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@ -22,9 +21,8 @@ import com.google.android.material.appbar.AppBarLayout.OnOffsetChangedListener
import com.google.android.material.appbar.CollapsingToolbarLayout
import com.todoroo.andlib.utility.AndroidUtilities
import dagger.hilt.android.AndroidEntryPoint
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.subjects.PublishSubject
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.tasks.Event
import org.tasks.PermissionUtil.verifyPermissions
@ -52,7 +50,6 @@ import org.tasks.preferences.Preferences
import org.tasks.themes.ColorProvider
import org.tasks.themes.Theme
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import kotlin.math.abs
@ -80,14 +77,13 @@ class LocationPickerActivity : InjectingAppCompatActivity(), Toolbar.OnMenuItemC
@Inject lateinit var firebase: Firebase
@Inject lateinit var preferences: Preferences
private var disposables: CompositeDisposable? = null
private var mapPosition: MapPosition? = null
private var recentsAdapter: LocationPickerAdapter? = null
private var searchAdapter: LocationSearchAdapter? = null
private var places: List<PlaceUsage> = emptyList()
private var offset = 0
private lateinit var search: MenuItem
private val searchSubject = PublishSubject.create<String>()
private var searchJob: Job? = null
private val viewModel: PlaceSearchViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
@ -290,12 +286,12 @@ class LocationPickerActivity : InjectingAppCompatActivity(), Toolbar.OnMenuItemC
override fun onResume() {
super.onResume()
map.onResume()
viewModel.observe(this, Observer { list: List<PlaceSearchResult?>? -> searchAdapter!!.submitList(list) }, Observer { place: Place? -> returnPlace(place) }, Observer { error: Event<String> -> handleError(error) })
disposables = CompositeDisposable(
searchSubject
.debounce(SEARCH_DEBOUNCE_TIMEOUT.toLong(), TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { query: String? -> viewModel.query(query, map.mapPosition) })
viewModel.observe(
this,
{ searchAdapter!!.submitList(it) },
{ returnPlace(it) },
{ handleError(it) }
)
}
override fun onDestroy() {
@ -341,7 +337,6 @@ class LocationPickerActivity : InjectingAppCompatActivity(), Toolbar.OnMenuItemC
override fun onPause() {
super.onPause()
map.onPause()
disposables!!.dispose()
}
override fun onSaveInstanceState(outState: Bundle) {
@ -370,7 +365,11 @@ class LocationPickerActivity : InjectingAppCompatActivity(), Toolbar.OnMenuItemC
override fun onQueryTextSubmit(query: String): Boolean = false
override fun onQueryTextChange(query: String): Boolean {
searchSubject.onNext(query)
searchJob?.cancel()
searchJob = lifecycleScope.launch {
delay(SEARCH_DEBOUNCE_TIMEOUT)
viewModel.query(query, map.mapPosition)
}
return true
}
@ -396,6 +395,6 @@ class LocationPickerActivity : InjectingAppCompatActivity(), Toolbar.OnMenuItemC
const val EXTRA_PLACE = "extra_place"
private const val EXTRA_MAP_POSITION = "extra_map_position"
private const val EXTRA_APPBAR_OFFSET = "extra_appbar_offset"
private const val SEARCH_DEBOUNCE_TIMEOUT = 300
private const val SEARCH_DEBOUNCE_TIMEOUT = 300L
}
}
Loading…
Cancel
Save