Я создаю приложение, которое позволяет пользователю искать местоположение. Используя SearchView, приложение выполняет вызов API и показывает результат в RecyclerView. Когда пользователь впервые загружает приложение, оно показывает историю поиска, которую можно фильтровать. Моя проблема в том, что когда я вызываю api и закрываю SearchView, я вижу предыдущую историю местоположений плюс результаты вызова api в нижней части RecyclerView. Как мне обновить sh результаты, чтобы увидеть новую историю поиска только при закрытии SearchView?
Это моя активность:
class MainActivity : AppCompatActivity(), SearchView.OnQueryTextListener, SearchView.OnCloseListener {
@Inject
lateinit var mainViewModelFactory: MainViewModelFactory
private lateinit var mainViewModel: MainViewModel
private lateinit var searchView: SearchView
private val adapter = LocationListAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.searchHistoryRecyclerView.adapter = adapter
binding.searchHistoryRecyclerView.layoutManager = LinearLayoutManager(this)
mainViewModel = ViewModelProvider(this, mainViewModelFactory).get(MainViewModel::class.java)
mainViewModel.searchHistory.observe(this, Observer { locationList ->
locationList?.let {
adapter.loadLocations(locationList.toMutableList())
}
})
mainViewModel.searchResults.observe(this, Observer { locationList ->
locationList?.let {
adapter.loadLocations(locationList.toMutableList())
}
})
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.menu_main, menu)
val searchItem = menu?.findItem(R.id.action_search)
if (searchItem != null) {
searchView = searchItem.actionView as SearchView
searchView.queryHint = "Search for a location"
searchView.setOnQueryTextListener(this)
}
return super.onCreateOptionsMenu(menu)
}
override fun onQueryTextSubmit(query: String?): Boolean {
if(!query.isNullOrEmpty()) performSearch(query)
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
adapter.filter.filter(newText)
return false
}
private fun performSearch(query: String) {
mainViewModel.setCity(query)
}
override fun onClose(): Boolean {
adapter.filter.filter("")
return false
}
}
Модель представления:
class MainViewModel @Inject constructor(private val weatherRepository: WeatherRepository) : ViewModel() {
val searchHistory: LiveData<List<Location>> = liveData(Dispatchers.IO) {
emit(weatherRepository.getSearchHistory())
}
private val city = MutableLiveData<String>()
val searchResults: LiveData<List<Location>> = city.switchMap {
liveData(Dispatchers.IO) {
emit(weatherRepository.getLocationsFromApi(it))
weatherRepository.save(Location(name = it, countryCode = it))
}
}
fun setCity(newCity: String) {
city.value = newCity
}
}
И адаптер:
class LocationListAdapter : RecyclerView.Adapter<LocationListAdapter.ViewHolder>(), Filterable {
private var locations = mutableListOf<Location>()
private var locationListFull = mutableListOf<Location>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.recyclerview_item, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(locations[position])
}
override fun getItemCount(): Int =locations.size
fun loadLocations(list: MutableList<Location>) {
locations = list
locationListFull.addAll(locations)
notifyDataSetChanged()
}
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(item: Location) {
itemView.locationTextView.text = item.name
}
}
override fun getFilter(): Filter {
return simpleSearchFilter
}
private val simpleSearchFilter: Filter = object : Filter() {
override fun performFiltering(constraint: CharSequence?): FilterResults {
val filteredList: MutableList<Location> = mutableListOf()
if (constraint.isNullOrEmpty()) {
filteredList.addAll(locationListFull)
} else {
val filterPattern = constraint.toString().toLowerCase()
for (item in locationListFull) {
if (item.name.toLowerCase().contains(filterPattern)) {
filteredList.add(item)
}
}
}
val results = FilterResults()
results.values = filteredList
return results
}
@Suppress("UNCHECKED_CAST")
override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
locations.clear()
locations.addAll(results?.values as MutableList<Location>)
notifyDataSetChanged()
}
}
}