Hey everyone :smile: Can anyone look at this snip...
# android
a
Hey everyone 😄 Can anyone look at this snippet and tell me why
listOfRides.map { ... }
freezes the app?
Copy code
private fun initUserAndRides() {

    // TODO: Fix this
    viewModelScope.launch {

        val userInstance = repository.getUser()
        val listOfRides =
            repository.getRides()

        _user.postValue(userInstance)

        withContext(Dispatchers.Default) {
            val listOfUserRides = listOfRides.map { UserRide.createUserRide(userInstance, it) }
            _rides.postValue(listOfUserRides)
        }
    }
}
Please know that
UserRide.createUserRide(userInstance, it)
is computationally-expensive. Also,
repository.getUser()
and
repository.getRides()
are suspend functions implemented by Retrofit.
s
Did you try with IO dispatcher?
a
I did. Will try and remove even more specific parts of code. Hopefully that'll give me a hint.
Okay, so here's what I know so far: • I'm receiving some data from the Repository in my ViewModel. This data needs to be processed. • Inside my ViewModel's
init {}
, I'm fetching that data, mapping it to get the processed data, then setting this processed data to a LiveData's value. • The problem is the mapping... Each data element requires binary search to get mapped properly, and somehow that stops the coroutine without any error.
Here are the snippets: ViewModel
Copy code
init {
    initUserAndRides()
}

private fun initUserAndRides() {

    viewModelScope.launch {
        val userInstance = repository.getUser()
        val listOfRides =
            repository.getRides()

        val listOfUserRides = mapRidesToUserRides(listOfRides, userInstance)

        _user.value = userInstance
        _rides.value = listOfUserRides
    }
}

private suspend fun mapRidesToUserRides(listOfRides: List<Ride>, user: User): List<UserRide> {
    return withContext(Dispatchers.Default) {
        listOfRides.map { UserRide.createUserRide(user, it) }
    }
}
UserRide
Copy code
// TODO: computeDistance freezes screen
fun createUserRide(user: User, ride: Ride): UserRide {
    return UserRide(
        user = user,
        ride = ride,
        date = processDate(ride.date),
        distance = computeDistance(user.station_code, ride.station_path)
    )
}

fun computeDistance(userStationCode: Int, stationPath: List<Int>): Int {

    val closestStationCode = findClosest(userStationCode, stationPath)

    return abs(closestStationCode - userStationCode)
}

private fun findClosest(userStationCode: Int, stationPath: List<Int>): Int {

    if (userStationCode <= stationPath.first()) {
        return stationPath.first()
    }

    if (userStationCode >= stationPath.last()) {
        return stationPath.last()
    }

    if (stationPath.size > 2) {
        // Binary Search
        var low = 0
        var high = stationPath.lastIndex

        while (low + 1 < high) {
            val mid = low + (high - 1) / 2
            if (stationPath[mid] == userStationCode) {
                return stationPath[mid]
            }

            if (stationPath[mid] > userStationCode) {
                high = mid
            } else {
                low = mid
            }
        }

        // Post processing
        return if (abs(stationPath[low] - userStationCode) < abs(stationPath[high] - userStationCode))
            stationPath[low]
        else stationPath[high]


    }

    // Linear Search
    return if (abs(stationPath[0] - userStationCode) < abs(stationPath[1] - userStationCode))
        stationPath[0]
    else stationPath[1]
}