diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/CollarListActivity.kt b/app/src/main/java/com/danilafe/fencelessgrazing/CollarListActivity.kt index 5ca61b4..ee217b4 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/CollarListActivity.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/CollarListActivity.kt @@ -2,19 +2,35 @@ package com.danilafe.fencelessgrazing import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.widget.Toast import androidx.preference.PreferenceManager import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.android.volley.RequestQueue +import com.android.volley.Response +import com.android.volley.toolbox.Volley +import com.danilafe.fencelessgrazing.model.CollarSummary +import com.danilafe.fencelessgrazing.requests.CollarRequest import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.TileSourceFactory +import org.osmdroid.util.GeoPoint import org.osmdroid.views.MapView +import org.osmdroid.views.overlay.Marker class CollarListActivity : AppCompatActivity() { - private lateinit var token: String + // The list of collar summaries and its list adapter. + private val summaries : MutableList = mutableListOf() private lateinit var summaryAdapter: CollarSummaryAdapter + + // The API token and request queue. + private lateinit var token: String + private lateinit var queue: RequestQueue + + // The OpenStreetMap map. private lateinit var map: MapView + private val collarOverlays: MutableMap = mutableMapOf() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -27,14 +43,15 @@ class CollarListActivity : AppCompatActivity() { val collarList: RecyclerView = findViewById(R.id.collarSummaryList) val layoutManager = LinearLayoutManager(collarList.context) token = intent.getStringExtra("token")!! - summaryAdapter = CollarSummaryAdapter(collarList.context, getString(R.string.apiUrl), token) + summaryAdapter = CollarSummaryAdapter(summaries) map = findViewById(R.id.map) map.setTileSource(TileSourceFactory.MAPNIK) + queue = Volley.newRequestQueue(this) collarList.adapter = summaryAdapter collarList.layoutManager = layoutManager collarList.addItemDecoration(DividerItemDecoration(collarList.context, layoutManager.orientation)) - summaryAdapter.triggerRefresh() + triggerRefresh() } override fun onResume() { @@ -47,4 +64,41 @@ class CollarListActivity : AppCompatActivity() { map.onPause() } + private fun triggerRefresh() { + val request = CollarRequest(getString(R.string.apiUrl), token, + Response.Listener { + summaries.clear() + summaries.addAll(it) + summaryAdapter.notifyDataSetChanged() + updateMapOverlay() + }, + Response.ErrorListener { + Toast.makeText(this, "Failed to retrieve collar list!", Toast.LENGTH_SHORT).show() + } + ) + queue.add(request) + } + + private fun updateMapOverlay() { + val currentSet = mutableSetOf() + summaries.forEach { + // Create or update overlay + val overlay = collarOverlays[it.id] ?: Marker(map) + overlay.title = it.name + overlay.position = GeoPoint(it.pos.longitude.toDouble(), it.pos.latitude.toDouble()) + + // Store new / existing overlay. + if(!collarOverlays.containsKey(it.id)) map.overlays.add(overlay) + collarOverlays[it.id] = overlay + currentSet.add(it.id) + } + + val previousSet = collarOverlays.keys + previousSet.forEach { + if(!currentSet.contains(it)) { + map.overlays.remove(collarOverlays[it]) + collarOverlays.remove(it) + } + } + } } diff --git a/app/src/main/java/com/danilafe/fencelessgrazing/CollarSummaryAdapter.kt b/app/src/main/java/com/danilafe/fencelessgrazing/CollarSummaryAdapter.kt index b20caf1..9611a8f 100644 --- a/app/src/main/java/com/danilafe/fencelessgrazing/CollarSummaryAdapter.kt +++ b/app/src/main/java/com/danilafe/fencelessgrazing/CollarSummaryAdapter.kt @@ -12,9 +12,7 @@ import com.danilafe.fencelessgrazing.model.CollarSummary import com.danilafe.fencelessgrazing.requests.CollarRequest class CollarSummaryAdapter( - private val context: Context, - private val baseUrl: String, - private val token: String + private val items : List ) : ListAdapter(DiffCallback()) { class DiffCallback : DiffUtil.ItemCallback() { @@ -25,9 +23,6 @@ class CollarSummaryAdapter( = oldItem == newItem } - private val requestQueue = Volley.newRequestQueue(context) - private val items = mutableListOf() - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CollarViewHolder { val layout = LayoutInflater.from(parent.context).inflate(viewType, parent, false) return CollarViewHolder(layout) @@ -43,18 +38,5 @@ class CollarSummaryAdapter( override fun getItemCount(): Int = items.size - fun triggerRefresh() { - val request = CollarRequest(baseUrl, token, - Response.Listener { - items.clear() - items.addAll(it) - notifyDataSetChanged() - }, - Response.ErrorListener { - Toast.makeText(context, "Failed to retrieve collar list!", Toast.LENGTH_SHORT).show() - } - ) - requestQueue.add(request) - } } \ No newline at end of file