Skip to main content
Signature
RelevantSortConnector(
    searcher: HitsSearcher,
    viewModel: RelevantSortViewModel
)

About this widget

Virtual indices let you use relevant sort, a sorting mechanism that favors relevancy over the attribute you’re sorting on. The relevantSort widget displays the current search mode when searching in a virtual replica index, and allows users to switch between relevant and regular sorting, which is more exhaustive but can return less relevant results.

Examples

Instantiate a RelevantSortConnector and connect it to a RelevantSortView.

Android view

Kotlin
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val relevantSort = RelevantSortConnector(searcher)
    val connection = ConnectionHandler(relevantSort)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val banner = findViewById<View>(R.id.banner)
        val button = findViewById<Button>(R.id.buttonBanner)
        val textView = findViewById<TextView>(R.id.labelBanner)
        val view = RelevantSortBanner(banner, button, textView)
        connection += relevantSort.connectView(view) { priority ->
            when (priority) {
                RelevantSortPriority.Relevancy -> RelevantSortText.Relevant
                RelevantSortPriority.HitsCount -> RelevantSortText.All
                else -> null // the index does not support Relevant sort
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        connection.disconnect()
        searcher.cancel()
    }
}

class RelevantSortBanner(val banner: View, val button: Button, val textView: TextView) : RelevantSortView<RelevantSortText?> {
    init { button.setOnClickListener { didToggle?.invoke() } }
    override var didToggle: (() -> Unit)? = null
    override fun updateView(input: RelevantSortText?) {
        when (input) {
            null -> banner.visibility = View.GONE
            else -> {
                banner.visibility = View.VISIBLE
                button.text = input.buttonText
                textView.text = input.label
            }
        }
    }
}

enum class RelevantSortText(val buttonText: String, val label: String) {
    Relevant("Show all results", "We removed some search results to show you the most relevant ones"),
    All("Show more relevant results", "Currently showing all results")
}

Compose UI

InstantSearch provides the RelevantSortState as a state model, which is an implementation of the RelevantSortView interface. RelevantSortState must be connected to the RelevantSortConnector or RelevantSortViewModel like any other RelevantSortView implementation.
Kotlin
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val relevantSortState = RelevantSortState<String?>(null)
    val relevantSort = RelevantSortConnector(searcher)
    val connections = ConnectionHandler(relevantSort)

    init {
        connections += relevantSort.connectView(relevantSortState) { priority ->
            when (priority) {
                RelevantSortPriority.Relevancy -> "We removed some search results to show you the most relevant ones"
                RelevantSortPriority.HitsCount -> "Currently showing all results"
                else -> null // the index does not support Relevant sort
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyRelevantSortBanner(relevantSortState) // your own UI composable to display relevant sort banner
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        connections.disconnect()
        searcher.cancel()
    }
}

Parameters

searcher
HitsSearcher
required
The Searcher that handles your searches.
viewModel
RelevantSortViewModel
default: RelevantSortViewModel()
The business logic handling the Relevant sort priority changes.

View

view
RelevantSortView<T>
required
The view that presents and toggles the relevant sort priority state. If you don’t need to transform anything, you can use RelevantSortPriorityView instead, which is a type alias of RelevantSortView<RelevantSortPriority?>.
presenter
RelevantSortPresenter<T>
required
Presenter transforming the Relevant sort priority state to its representation for a view. Not required if you use RelevantSortPriorityView.
Kotlin
class RelevantSortBanner(val textView: TextView, val button: Button) : RelevantSortView<String> {
    init { button.setOnClickListener { didToggle?.invoke() } }
    override var didToggle: (() -> Unit)? = null
    override fun updateView(input: String) { this.textView.text = input }
}

val textView = TextView(this)
val button = Button(this)
val relevantSort = RelevantSortConnector(searcher)
val view = RelevantSortBanner(textView, button)

relevantSortConnector.connectView(view) { priority ->
    when (priority) {
        RelevantSortPriority.Relevancy -> "Showing only relevant results."
        else -> "Showing all results!"
    }
}

Low-level API

If you want to fully control the RelevantSort components and connect them manually, you can use the following components:
  • Searcher. The Searcher that handles your searches.
  • RelevantSortViewModel. The business logic handling the Relevant sort priority changes.
  • RelevantSortView<T>. The view that presents and toggles the Relevant sort priority state. RelevantSortPriorityView is a type alias of RelevantSortView<RelevantSortPriority?>.
  • RelevantSortPresenter<T>. Generic presenter transforming the Relevant sort priority state to its representation for a view. Optional if you use RelevantSortPriorityView.
Kotlin
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = ApplicationID("YourApplicationID"),
        apiKey = APIKey("YourSearchOnlyAPIKey"),
        indexName = IndexName("YourIndexName")
    )
    val connection = ConnectionHandler()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val banner = findViewById<View>(R.id.banner)
        val button = findViewById<Button>(R.id.buttonBanner)
        val textView = findViewById<TextView>(R.id.labelBanner)
        val view = RelevantSortBanner(banner, button, textView)

        val viewModel = RelevantSortViewModel()
        connection += viewModel.connectSearcher(searcher)
        connection += viewModel.connectView(view) { priority ->
            when (priority) {
                RelevantSortPriority.Relevancy -> RelevantSortText.Relevant
                RelevantSortPriority.HitsCount -> RelevantSortText.All
                else -> null
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        connection.disconnect()
        searcher.cancel()
    }
}

class RelevantSortBanner(val banner: View, val button: Button, val textView: TextView) : RelevantSortView<RelevantSortText?> {
    init { button.setOnClickListener { didToggle?.invoke() } }
    override var didToggle: (() -> Unit)? = null
    override fun updateView(input: RelevantSortText?) {
        when (input) {
            null -> banner.visibility = View.GONE
            else -> {
                banner.visibility = View.VISIBLE
                button.text = input.buttonText
                textView.text = input.label
            }
        }
    }
}

enum class RelevantSortText(val buttonText: String, val label: String) {
    Relevant("Show all results", "We removed some search results to show you the most relevant ones"),
    All("Show more relevant results", "Currently showing all results")
}
I