Infinite Hits (Paging)
About this widget
Infinite Hits is a view with helpers that displays a paginated list of search results.
It leverages Android Architecture Components’ Paging library and LiveData to provide lifecycle-aware, observable search results that can be loaded as the user scrolls.
To add Infinite Hits to your search experience, use these components:
Searcher
: TheSearcher
that handles your searches.SearcherSingleIndexDataSource
: ThePageKeyedDataSource
that will load hits incrementally.LivePagedListBuilder
: The builder creatingLiveData
, based on the givenDataSource
andConfig
.T
: Adata class
representing a search result.FilterState
: In order for the paginated list to refresh when filters change.
Examples
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class MyActivity : AppCompatActivity() {
val client = ClientSearch(
ApplicationID("YourApplicationID"),
APIKey("YourAPIKey")
)
val index = client.initIndex(IndexName("YourIndexName"))
val searcher = SearcherSingleIndex(index)
val dataSourceFactory = SearcherSingleIndexDataSource.Factory(searcher) { it.deserialize(Movie.serializer()) }
val pagedListConfig = PagedList.Config.Builder()
.setPageSize(10) // configure according to your needs
.build()
val movies = LivePagedListBuilder<Int, Movie>(dataSourceFactory, pagedListConfig).build()
val filterState = FilterState()
val adapter = MovieAdapter()
val connection = ConnectionHandler()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
connection += filterState.connectPagedList(movies)
movies.observe(this, Observer { hits -> adapter.submitList(hits) })
searcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
searcher.cancel()
connection.disconnect()
}
}
@Serializable
data class Movie(
val title: String
)
class MovieViewHolder(val view: TextView) : RecyclerView.ViewHolder(view) {
fun bind(data: Movie) {
view.text = data.title
}
}
class MovieAdapter : PagedListAdapter<Movie, MovieViewHolder>(MovieAdapter) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieViewHolder {
return MovieViewHolder(TextView(parent.context))
}
override fun onBindViewHolder(holder: MovieViewHolder, position: Int) {
val movie = getItem(position)
if (movie != null) holder.bind(movie)
}
companion object : DiffUtil.ItemCallback<Movie>() {
override fun areItemsTheSame(
oldItem: Movie,
newItem: Movie
): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(
oldItem: Movie,
newItem: Movie
): Boolean {
return oldItem.title == newItem.title
}
}
}
Compose UI
InstantSearch provides the Paginator
, which exposes a flow
property for paging data, and an invalidate()
method to stop loading.
You need to connect Paginator
to other components, such as SearchBoxConnector
, FilterState
, or FacetListConnector
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class MyActivity : AppCompatActivity() {
val client = ClientSearch(
ApplicationID("YourApplicationID"),
APIKey("YourAPIKey")
)
val index = client.initIndex(IndexName("YourIndexName"))
val searcher = SearcherSingleIndex(index)
val pagingConfig = PagingConfig(pageSize = 10)
val hitsPaginator = Paginator(searcher, pagingConfig) { it.deserialize(Movie.serializer()) }
val searchBoxState = SearchBoxState()
val searchBox = SearchBoxConnector(searcher)
val connections = ConnectionHandler()
init {
connections += searchBox.connectView(searchBoxState)
connections += searchBox.connectPaginator(hitsPaginator)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SearchBox(
searchBoxState = searchBoxState
)
val hitsPaging = hitsPaginator.flow.collectAsLazyPagingItems()
LazyColumn {
items(hitsPaging) { movie ->
movie?.let { Text(it.title) }
}
}
}
searcher.searchAsync()
}
override fun onDestroy() {
super.onDestroy()
connections.disconnect()
searcher.cancel()
}
}
Parameters
observer
|
type: Observer<in PagedList<T>>
Required
A function called on new hits. You should forward the hits the UI to display them. |
||
Copy
|