avoid usage of instanceState (use viewmodel instead)

use viewModel to keep track of query

change handling for textChanged listener

minor changes

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2023-10-02 15:07:32 +02:00
parent 16f6e3c0cd
commit 8f15c3c1e7
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
3 changed files with 41 additions and 70 deletions

View File

@ -20,6 +20,7 @@
package com.nextcloud.talk.adapters package com.nextcloud.talk.adapters
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@ -35,6 +36,8 @@ class GeocodingAdapter(private val context: Context, private var dataSource: Lis
interface OnItemClickListener { interface OnItemClickListener {
fun onItemClick(position: Int) fun onItemClick(position: Int)
} }
@SuppressLint("NotifyDataSetChanged")
fun updateData(data: List<Address>) { fun updateData(data: List<Address>) {
this.dataSource = data this.dataSource = data
notifyDataSetChanged() notifyDataSetChanged()

View File

@ -32,8 +32,6 @@ import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.core.view.MenuItemCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -55,8 +53,7 @@ import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class GeocodingActivity : class GeocodingActivity :
BaseActivity(), BaseActivity() {
SearchView.OnQueryTextListener {
private lateinit var binding: ActivityGeocodingBinding private lateinit var binding: ActivityGeocodingBinding
@ -67,11 +64,10 @@ class GeocodingActivity :
lateinit var okHttpClient: OkHttpClient lateinit var okHttpClient: OkHttpClient
lateinit var roomToken: String lateinit var roomToken: String
var nominatimClient: TalkJsonNominatimClient? = null private var nominatimClient: TalkJsonNominatimClient? = null
var searchItem: MenuItem? = null private var searchItem: MenuItem? = null
var searchView: SearchView? = null var searchView: SearchView? = null
var query: String? = null
lateinit var adapter: GeocodingAdapter lateinit var adapter: GeocodingAdapter
private var geocodingResults: List<Address> = ArrayList() private var geocodingResults: List<Address> = ArrayList()
@ -90,34 +86,24 @@ class GeocodingActivity :
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context)) Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))
roomToken = intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN)!! roomToken = intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN)!!
query = intent.getStringExtra(BundleKeys.KEY_GEOCODING_QUERY)
recyclerView = findViewById(R.id.geocoding_results) recyclerView = findViewById(R.id.geocoding_results)
recyclerView.layoutManager = LinearLayoutManager(this) recyclerView.layoutManager = LinearLayoutManager(this)
adapter = GeocodingAdapter(this, geocodingResults) adapter = GeocodingAdapter(this, geocodingResults)
recyclerView.adapter = adapter recyclerView.adapter = adapter
viewModel = ViewModelProvider(this).get(GeoCodingViewModel::class.java) viewModel = ViewModelProvider(this)[GeoCodingViewModel::class.java]
query = viewModel.getQuery() var query = viewModel.getQuery()
if (query.isNullOrEmpty()) { if (query.isEmpty() && intent.hasExtra(BundleKeys.KEY_GEOCODING_QUERY)) {
query = intent.getStringExtra(BundleKeys.KEY_GEOCODING_QUERY) query = intent.getStringExtra(BundleKeys.KEY_GEOCODING_QUERY).orEmpty()
viewModel.setQuery(query ?: "") viewModel.setQuery(query)
} }
val savedResults = viewModel.getGeocodingResults() val savedResults = viewModel.getGeocodingResults()
initAdapter(savedResults) initAdapter(savedResults)
viewModel.getGeocodingResultsLiveData().observe( viewModel.getGeocodingResultsLiveData().observe(this) { results ->
this, geocodingResults = results
Observer { results -> adapter.updateData(results)
geocodingResults = results }
adapter.updateData(results)
}
)
viewModel.getQueryLiveData().observe(
this,
Observer { newQuery ->
query = newQuery
searchView?.setQuery(query, false)
}
)
val baseUrl = getString(R.string.osm_geocoder_url) val baseUrl = getString(R.string.osm_geocoder_url)
val email = context.getString(R.string.osm_geocoder_contact) val email = context.getString(R.string.osm_geocoder_contact)
nominatimClient = TalkJsonNominatimClient(baseUrl, okHttpClient, email) nominatimClient = TalkJsonNominatimClient(baseUrl, okHttpClient, email)
@ -132,8 +118,8 @@ class GeocodingActivity :
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (!query.isNullOrEmpty()) { if (viewModel.getQuery().isNotEmpty() && adapter.itemCount == 0) {
viewModel.searchLocation(query!!) viewModel.searchLocation()
} else { } else {
Log.e(TAG, "search string that was passed to GeocodingController was null or empty") Log.e(TAG, "search string that was passed to GeocodingController was null or empty")
} }
@ -148,7 +134,7 @@ class GeocodingActivity :
startActivity(intent) startActivity(intent)
} }
}) })
searchView?.setQuery(query, false) searchView?.setQuery(viewModel.getQuery(), false)
} }
private fun setupActionBar() { private fun setupActionBar() {
@ -184,43 +170,17 @@ class GeocodingActivity :
menuInflater.inflate(R.menu.menu_geocoding, menu) menuInflater.inflate(R.menu.menu_geocoding, menu)
searchItem = menu.findItem(R.id.geocoding_action_search) searchItem = menu.findItem(R.id.geocoding_action_search)
initSearchView() initSearchView()
searchItem?.expandActionView() searchItem?.expandActionView()
searchView?.setQuery(query, false) searchView?.setQuery(viewModel.getQuery(), false)
searchView?.clearFocus() searchView?.clearFocus()
return true return true
} }
override fun onQueryTextSubmit(query: String?): Boolean {
this.query = query ?: ""
viewModel.setQuery(this.query!!)
if (query != null) {
viewModel.searchLocation(query)
}
searchView?.clearFocus()
return true
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
query?.let { viewModel.setQuery(it) }
outState.putString(KEY_SEARCH_QUERY, query)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
query = viewModel.getQuery()
query = savedInstanceState.getString(KEY_SEARCH_QUERY)
}
override fun onQueryTextChange(newText: String?): Boolean {
return true
}
private fun initSearchView() { private fun initSearchView() {
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
if (searchItem != null) { if (searchItem != null) {
searchView = MenuItemCompat.getActionView(searchItem) as SearchView searchView = searchItem!!.actionView as SearchView?
searchView?.maxWidth = Int.MAX_VALUE searchView?.maxWidth = Int.MAX_VALUE
searchView?.inputType = InputType.TYPE_TEXT_VARIATION_FILTER searchView?.inputType = InputType.TYPE_TEXT_VARIATION_FILTER
var imeOptions = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN var imeOptions = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
@ -230,7 +190,23 @@ class GeocodingActivity :
searchView?.imeOptions = imeOptions searchView?.imeOptions = imeOptions
searchView?.queryHint = resources!!.getString(R.string.nc_search) searchView?.queryHint = resources!!.getString(R.string.nc_search)
searchView?.setSearchableInfo(searchManager.getSearchableInfo(componentName)) searchView?.setSearchableInfo(searchManager.getSearchableInfo(componentName))
searchView?.setOnQueryTextListener(this) searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
viewModel.setQuery(query)
viewModel.searchLocation()
searchView?.clearFocus()
return true
}
override fun onQueryTextChange(query: String): Boolean {
// This is a workaround to not set viewModel data when onQueryTextChange is triggered on startup
// Otherwise it would be set to an empty string.
if (searchView?.width!! > 0) {
viewModel.setQuery(query)
}
return true
}
})
searchItem?.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { searchItem?.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(menuItem: MenuItem): Boolean { override fun onMenuItemActionExpand(menuItem: MenuItem): Boolean {
@ -256,6 +232,5 @@ class GeocodingActivity :
companion object { companion object {
val TAG = GeocodingActivity::class.java.simpleName val TAG = GeocodingActivity::class.java.simpleName
const val KEY_SEARCH_QUERY = "search_query"
} }
} }

View File

@ -36,7 +36,6 @@ import java.io.IOException
class GeoCodingViewModel : ViewModel() { class GeoCodingViewModel : ViewModel() {
private val geocodingResultsLiveData = MutableLiveData<List<Address>>() private val geocodingResultsLiveData = MutableLiveData<List<Address>>()
private val queryLiveData = MutableLiveData<String>()
private val nominatimClient: TalkJsonNominatimClient private val nominatimClient: TalkJsonNominatimClient
private val okHttpClient: OkHttpClient = OkHttpClient.Builder().build() private val okHttpClient: OkHttpClient = OkHttpClient.Builder().build()
private var geocodingResults: List<Address> = ArrayList() private var geocodingResults: List<Address> = ArrayList()
@ -45,18 +44,12 @@ class GeoCodingViewModel : ViewModel() {
return geocodingResultsLiveData return geocodingResultsLiveData
} }
fun getQueryLiveData(): LiveData<String> {
return queryLiveData
}
fun getQuery(): String { fun getQuery(): String {
return query return query
} }
fun setQuery(query: String) { fun setQuery(query: String) {
if (queryLiveData.value.isNullOrEmpty()) { this.query = query
queryLiveData.value = query
}
} }
fun getGeocodingResults(): List<Address> { fun getGeocodingResults(): List<Address> {
@ -71,7 +64,7 @@ class GeoCodingViewModel : ViewModel() {
) )
} }
fun searchLocation(query: String) { fun searchLocation() {
if (query.isNotEmpty()) { if (query.isNotEmpty()) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
try { try {