Skip to content
This repository was archived by the owner on Feb 17, 2020. It is now read-only.

Commit b93ce66

Browse files
authored
Merge pull request #533 from squanchy-dev/fix_search
Fix a crash in the SearchActivity and improve its state management
2 parents bc2368c + c15554d commit b93ce66

4 files changed

Lines changed: 27 additions & 16 deletions

File tree

app/src/main/java/net/squanchy/search/SearchActivity.kt

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,16 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
4646
private lateinit var searchTextWatcher: SearchTextWatcher
4747

4848
private var hasQuery: Boolean = false
49+
private lateinit var initialQuery: String
4950

5051
override fun onCreate(savedInstanceState: Bundle?) {
5152
super.onCreate(savedInstanceState)
5253
setContentView(R.layout.activity_search)
5354
enableLightNavigationBar(this)
5455
setupToolbar()
5556

57+
initialQuery = savedInstanceState?.getString(QUERY_KEY) ?: ""
58+
5659
with(searchComponent(this)) {
5760
searchService = service()
5861
navigator = navigator()
@@ -72,10 +75,9 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
7275
searchTextWatcher = SearchTextWatcher(querySubject)
7376
searchField.addTextChangedListener(searchTextWatcher)
7477

75-
val searchSubscription = querySubject.distinctUntilChanged()
76-
.debounce(QUERY_DEBOUNCE_TIMEOUT, TimeUnit.MILLISECONDS)
78+
val searchSubscription = querySubject.throttleLast(QUERY_DEBOUNCE_TIMEOUT, TimeUnit.MILLISECONDS)
7779
.doOnNext(::updateSearchActionIcon)
78-
.startWith(getInitialQuery())
80+
.startWith(initialQuery)
7981
.flatMap(searchService::find)
8082
.distinctUntilChanged()
8183
.subscribeOn(Schedulers.io())
@@ -94,11 +96,6 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
9496
searchField.requestFocus()
9597
}
9698

97-
private fun getInitialQuery(): String {
98-
val text = searchField.text
99-
return text?.toString() ?: EMPTY_QUERY
100-
}
101-
10299
private fun updateSearchActionIcon(query: String) {
103100
hasQuery = query.isNotEmpty()
104101
invalidateOptionsMenu()
@@ -123,9 +120,8 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
123120
} else {
124121
emptyView.isInvisible = true
125122
searchRecyclerView.isVisible = true
126-
127-
searchRecyclerView.updateWith(searchResult, this)
128123
}
124+
searchRecyclerView.updateWith(searchResult, this)
129125
}
130126

131127
private fun onSearchError() {
@@ -193,6 +189,11 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
193189
}
194190
}
195191

192+
override fun onSaveInstanceState(outState: Bundle?) {
193+
outState?.putString(QUERY_KEY, searchField.text?.toString())
194+
super.onSaveInstanceState(outState)
195+
}
196+
196197
private fun onVoiceSearchClicked() {
197198
Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
198199
putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1)
@@ -246,6 +247,6 @@ class SearchActivity : AppCompatActivity(), SearchRecyclerView.OnSearchResultCli
246247
private const val SPEECH_REQUEST_CODE = 100
247248
private const val QUERY_DEBOUNCE_TIMEOUT = 250L
248249
private const val MIN_QUERY_LENGTH = 2
249-
private const val EMPTY_QUERY = ""
250+
private const val QUERY_KEY = "SearchActivity.query_key"
250251
}
251252
}

app/src/main/java/net/squanchy/search/SearchService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class SearchService(
5151
}
5252

5353
private fun createResultForQueryNotLongEnough(speakers: List<Speaker>): List<SearchListElement> {
54-
return listOf(SpeakerHeader) + speakers.map(::SpeakerElement)
54+
return listOf(SpeakerHeader) + speakers.map(::SpeakerElement).sortedBy { it.speaker.name }
5555
}
5656

5757
private fun createResultForSuccessfulSearch(events: List<Event>, speakers: List<Speaker>): List<SearchListElement> {

app/src/main/java/net/squanchy/search/view/GridSpanSizeLookup.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,22 @@ package net.squanchy.search.view
33
import android.support.v7.widget.GridLayoutManager
44
import net.squanchy.search.SearchListElement
55

6-
internal class GridSpanSizeLookup(private val items: List<SearchListElement>, private val columnCount: Int) : GridLayoutManager.SpanSizeLookup() {
6+
internal class GridSpanSizeLookup(
7+
private val itemRetriever: (Int) -> SearchListElement,
8+
private val isAdapterEmpty: () -> Boolean,
9+
private val columnCount: Int
10+
) : GridLayoutManager.SpanSizeLookup() {
711

812
init {
913
super.setSpanIndexCacheEnabled(true)
1014
}
1115

1216
override fun getSpanSize(position: Int): Int {
13-
return if (items.isEmpty()) SINGLE_COLUMN_SPAN_SIZE else getSpanSizeFor(items[position])
17+
if (isAdapterEmpty()) {
18+
return SINGLE_COLUMN_SPAN_SIZE
19+
} else {
20+
return getSpanSizeFor(itemRetriever(position))
21+
}
1422
}
1523

1624
private fun getSpanSizeFor(element: SearchListElement): Int =

app/src/main/java/net/squanchy/search/view/SearchAdapter.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ internal class SearchAdapter(activity: AppCompatActivity) : ListAdapter<SearchLi
7979
}
8080

8181
override fun onBindViewHolder(holder: SearchItemViewHolder, position: Int) {
82-
val item = searchResult.elements[position]
82+
val item = getItem(position)
8383
when (item) {
8484
is SearchListElement.EventHeader -> (holder as HeaderViewHolder).updateWith(HeaderType.EVENTS)
8585
is SearchListElement.SpeakerHeader -> (holder as HeaderViewHolder).updateWith(HeaderType.SPEAKERS)
@@ -90,9 +90,11 @@ internal class SearchAdapter(activity: AppCompatActivity) : ListAdapter<SearchLi
9090
}
9191

9292
fun createSpanSizeLookup(columnsCount: Int): GridLayoutManager.SpanSizeLookup {
93-
return GridSpanSizeLookup(searchResult.elements, columnsCount)
93+
return GridSpanSizeLookup(::getItem, ::isEmpty, columnsCount)
9494
}
9595

96+
private fun isEmpty() = itemCount == 0
97+
9698
fun updateWith(searchResult: SearchResult.Success, listener: SearchRecyclerView.OnSearchResultClickListener) {
9799
this.listener = listener
98100
this.searchResult = searchResult

0 commit comments

Comments
 (0)