> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# RelevantSort

> Lets users switch between search modes, exhaustive or relevant sorting.

```kotlin Signature theme={"system"}
RelevantSortConnector(
    searcher: HitsSearcher,
    viewModel: RelevantSortViewModel
)
```

<Card title="Explore example code" icon="github" href="https://github.com/algolia/instantsearch-android/tree/master/examples/android">
  Browse the RelevantSort example code on GitHub.
</Card>

## About this widget

Virtual indices let you use [relevant sort](/doc/guides/managing-results/refine-results/sorting/in-depth/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 Kotlin icon=code theme={"system"}
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = "YourApplicationID",
        apiKey = "YourSearchOnlyAPIKey",
        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 Kotlin icon=code theme={"system"}
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = "YourApplicationID",
        apiKey = "YourSearchOnlyAPIKey",
        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

<ParamField body="searcher" type="HitsSearcher" required>
  The [`Searcher`](/doc/api-reference/widgets/instantsearch/android) that handles your searches.
</ParamField>

<ParamField body="viewModel" type="RelevantSortViewModel" post={["default: RelevantSortViewModel()"]}>
  The business logic handling the Relevant sort priority changes.
</ParamField>

## View

<ParamField body="view" type="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?>`.
</ParamField>

<ParamField body="presenter" type="RelevantSortPresenter<T>" required>
  Presenter transforming the Relevant sort priority state to its representation for a view.
  Not required if you use `RelevantSortPriorityView`.

  ```kotlin Kotlin icon=code theme={"system"}
  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!"
      }
  }
  ```
</ParamField>

## 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`](/doc/api-reference/widgets/instantsearch/android) 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 Kotlin icon=code theme={"system"}
class MyActivity : AppCompatActivity() {
    val searcher = HitsSearcher(
        applicationID = "YourApplicationID",
        apiKey = "YourSearchOnlyAPIKey",
        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")
}
```
