mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-19 12:26:13 -04:00
Introduced a mutex to manage concurrency in the search functionality. This enables proper clearing of the first running job before executing a new one. By implementing this approach, we ensure that access to the libzim search results occurs one at a time, resolving the crashing issue caused by multiple attempts to access libzim resources.
* Replaced the `cancel` function for the Job with `cancelAndJoin`, ensuring that it thoroughly cancels the first job before initiating the new task.
This commit is contained in:
parent
6d5e50d0ef
commit
a07bb680c3
@ -43,7 +43,10 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancelAndJoin
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.kiwix.kiwixmobile.core.R
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||||
@ -86,6 +89,7 @@ class SearchFragment : BaseFragment() {
|
|||||||
private var searchAdapter: SearchAdapter? = null
|
private var searchAdapter: SearchAdapter? = null
|
||||||
private var isDataLoading = false
|
private var isDataLoading = false
|
||||||
private var renderingJob: Job? = null
|
private var renderingJob: Job? = null
|
||||||
|
private val searchMutex = Mutex()
|
||||||
|
|
||||||
override fun inject(baseActivity: BaseActivity) {
|
override fun inject(baseActivity: BaseActivity) {
|
||||||
baseActivity.cachedComponent.inject(this)
|
baseActivity.cachedComponent.inject(this)
|
||||||
@ -252,22 +256,25 @@ class SearchFragment : BaseFragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun render(state: SearchState) {
|
private suspend fun render(state: SearchState) {
|
||||||
renderingJob?.cancel()
|
searchMutex.withLock {
|
||||||
isDataLoading = false
|
// `cancelAndJoin` cancels the previous running job and waits for it to completely cancel.
|
||||||
searchInTextMenuItem?.isVisible = state.searchOrigin == FromWebView
|
renderingJob?.cancelAndJoin()
|
||||||
searchInTextMenuItem?.isEnabled = state.searchTerm.isNotBlank()
|
isDataLoading = false
|
||||||
fragmentSearchBinding?.searchLoadingIndicator?.isShowing(true)
|
searchInTextMenuItem?.isVisible = state.searchOrigin == FromWebView
|
||||||
renderingJob = searchViewModel.viewModelScope.launch(Dispatchers.Main) {
|
searchInTextMenuItem?.isEnabled = state.searchTerm.isNotBlank()
|
||||||
val searchResult = withContext(Dispatchers.IO) {
|
fragmentSearchBinding?.searchLoadingIndicator?.isShowing(true)
|
||||||
state.getVisibleResults(0, renderingJob)
|
renderingJob = searchViewModel.viewModelScope.launch(Dispatchers.Main) {
|
||||||
}
|
val searchResult = withContext(Dispatchers.IO) {
|
||||||
|
state.getVisibleResults(0, renderingJob)
|
||||||
|
}
|
||||||
|
|
||||||
fragmentSearchBinding?.searchLoadingIndicator?.isShowing(false)
|
fragmentSearchBinding?.searchLoadingIndicator?.isShowing(false)
|
||||||
|
|
||||||
searchResult?.let {
|
searchResult?.let {
|
||||||
fragmentSearchBinding?.searchNoResults?.isVisible = it.isEmpty()
|
fragmentSearchBinding?.searchNoResults?.isVisible = it.isEmpty()
|
||||||
searchAdapter?.items = it
|
searchAdapter?.items = it
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user