Add collar overlay to map

This commit is contained in:
Danila Fedorin 2020-02-16 17:40:30 -08:00
parent cfae237d17
commit 7b53546126
2 changed files with 58 additions and 22 deletions

View File

@ -2,19 +2,35 @@ package com.danilafe.fencelessgrazing
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
import android.widget.Toast
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView 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.config.Configuration
import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.Marker
class CollarListActivity : AppCompatActivity() { class CollarListActivity : AppCompatActivity() {
private lateinit var token: String // The list of collar summaries and its list adapter.
private val summaries : MutableList<CollarSummary> = mutableListOf()
private lateinit var summaryAdapter: CollarSummaryAdapter 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 lateinit var map: MapView
private val collarOverlays: MutableMap<Int, Marker> = mutableMapOf()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -27,14 +43,15 @@ class CollarListActivity : AppCompatActivity() {
val collarList: RecyclerView = findViewById(R.id.collarSummaryList) val collarList: RecyclerView = findViewById(R.id.collarSummaryList)
val layoutManager = LinearLayoutManager(collarList.context) val layoutManager = LinearLayoutManager(collarList.context)
token = intent.getStringExtra("token")!! token = intent.getStringExtra("token")!!
summaryAdapter = CollarSummaryAdapter(collarList.context, getString(R.string.apiUrl), token) summaryAdapter = CollarSummaryAdapter(summaries)
map = findViewById(R.id.map) map = findViewById(R.id.map)
map.setTileSource(TileSourceFactory.MAPNIK) map.setTileSource(TileSourceFactory.MAPNIK)
queue = Volley.newRequestQueue(this)
collarList.adapter = summaryAdapter collarList.adapter = summaryAdapter
collarList.layoutManager = layoutManager collarList.layoutManager = layoutManager
collarList.addItemDecoration(DividerItemDecoration(collarList.context, layoutManager.orientation)) collarList.addItemDecoration(DividerItemDecoration(collarList.context, layoutManager.orientation))
summaryAdapter.triggerRefresh() triggerRefresh()
} }
override fun onResume() { override fun onResume() {
@ -47,4 +64,41 @@ class CollarListActivity : AppCompatActivity() {
map.onPause() 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<Int>()
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)
}
}
}
} }

View File

@ -12,9 +12,7 @@ import com.danilafe.fencelessgrazing.model.CollarSummary
import com.danilafe.fencelessgrazing.requests.CollarRequest import com.danilafe.fencelessgrazing.requests.CollarRequest
class CollarSummaryAdapter( class CollarSummaryAdapter(
private val context: Context, private val items : List<CollarSummary>
private val baseUrl: String,
private val token: String
) : ListAdapter<CollarSummary, CollarViewHolder>(DiffCallback()) { ) : ListAdapter<CollarSummary, CollarViewHolder>(DiffCallback()) {
class DiffCallback : DiffUtil.ItemCallback<CollarSummary>() { class DiffCallback : DiffUtil.ItemCallback<CollarSummary>() {
@ -25,9 +23,6 @@ class CollarSummaryAdapter(
= oldItem == newItem = oldItem == newItem
} }
private val requestQueue = Volley.newRequestQueue(context)
private val items = mutableListOf<CollarSummary>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CollarViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CollarViewHolder {
val layout = LayoutInflater.from(parent.context).inflate(viewType, parent, false) val layout = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
return CollarViewHolder(layout) return CollarViewHolder(layout)
@ -43,18 +38,5 @@ class CollarSummaryAdapter(
override fun getItemCount(): Int = items.size 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)
}
} }