0

I have made a transport application that shows bus locations. I am currently trying to refactor my code so that I can smoothly animate markers (bus locations) and have seen that LiveData could be useful for cleaning up my code. I am using OkHttp to make my requests, a repository to return a mutableList of type BusInfo and then create markers from the mutable list of busInfo. My real problem is that my first call to the ViewModel works, but then when try to create a new instance of the viewmodel and get the updated daya, I return that exact same data from the first repository instance and a new instance is not being created. Is there any advice on how to periodically get a new mutable list of businfo from my viewmodel and update the markers position on the map. Can someone help me out? i am new enough to Kotlin and Android Dev in general.

class MapsFragment : Fragment(), OnMapReadyCallback {

private var mBusMap = HashMap<String, MarkerOptions>()
private var mBusHashMapUpdated = HashMap<String, MarkerOptions>()

val mBusInfoViewModel: BusInfoViewModel get() =
    ViewModelProviders.of(this).get(BusInfoViewModel::class.java)

private fun createBusMarkers(busMap:HashMap<String, MarkerOptions>,buses: MutableList<BusInfo>) {
    try {
        requireActivity().runOnUiThread {
            buses.forEach { bus ->
                busMap[bus.licenseNum] = createMarker(
                    bus.licenseNum,
                    LatLng(bus.lat, bus.long),
                    createScaledBitmap(R.drawable.bus_icon_green),
                    bus.licenseNum,
                    bus.direction,
                    bus.speed
                )
                busMap.forEach { s, marker ->
                    mMap.addMarker(marker)
                }
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

override fun onMapReady(googleMap: GoogleMap) {
    mMap = googleMap

    mBusInfoViewModel.reposResult.observe(this, android.arch.lifecycle.Observer {
        if (it != null) {
            createBusMarkers(mBusMap, it)
        }
    })
    updateBusesPeriodically()
}

private fun updateBusesPeriodically() {
    val timer = Timer()
    GlobalScope.launch {
        timer.scheduleAtFixedRate(10000, 10000) {                 
            updateBusMarkers()
        }
    }
}
private fun updateBusMarkers() {
        busInfoViewModel.reposResult.observe(this, android.arch.lifecycle.Observer {
            if (it != null) {
                createBusMarkers(mBusHashMapUpdated, it)
            }
        }
...animate each marker moving from old position to new position
)}
    }

I have created a viewmodel for the returning the Mutable list of type BusInfo to the view on successful response form the OkHttp request.

class BusInfoViewModel : ViewModel() {
val reposResult = MutableLiveData<MutableList<BusInfo>>()

private var busInfoRepository = BusInfoRepository.instance()

init {
    loadBusInfoListFromUrl()
}

fun loadBusInfoListFromUrl(): MutableList<BusInfo> {
    return busInfoRepository.getBusInfoListFromResponseBody { repos ->
        reposResult.postValue(repos)
    }
}

I have added a repository class for getting the data fro the http request and returning the list of buses

class BusInfoRepository {

fun getBusInfoListFromResponseBody(completion: (MutableList<BusInfo>) -> Unit): MutableList<BusInfo> {
    val request = Request.Builder().url(url).build()
    val client = OkHttpClient()
    var buses = mutableListOf<BusInfo>()
    client.newCall(request).enqueue(object : Callback {

        override fun onResponse(call: okhttp3.Call?, response: okhttp3.Response?) {
            val stringResponse = response?.body()?.string()
            buses = createBusesFromResponseBody(stringResponse)
            completion(buses)
        }

        override fun onFailure(call: okhttp3.Call?, e: IOException?) {
            Log.e("Http API call failed", e?.message)
        }
    })
    return buses
}
}
atmalone
  • 11
  • 4

1 Answers1

0

I realised what I was doing incorrectly. The viewmodel was instantiated and loadBusInfoListFromUrl() was called, populating reposResult. The problem was I never updating the reposResult value after that. In the method for updating the viewmodel periodically, I should have been calling mBusInfoViewModel.loadBusInfoListFromUrl() in the updateBusMarkers method.

atmalone
  • 11
  • 4