Are using kotlin flow builder on function is creat...
# android
o
Are using kotlin flow builder on function is creating memory leak
Copy code
override fun getUsersSearch(username: String) = flow<Resource<List<UserDTO>>> {
    emit(Resource.Loading())

    localDataSource.getUserSearch(username).collect { fromDb ->
        when (fromDb) {
            is FromDb.Success -> {
                val dtos = mapNullInputList(fromDb.data) { it.toDto() }
                emit(Resource.Success(dtos))
            }
            is FromDb.Empty -> {
                when (val networkState = remoteDataSource.getUserSearch(username)) {
                    is FromNetwork.Success -> {
                        val fromNetwork = networkState.body

                        val cache = mapNullInputList(fromNetwork) { it.toEntity() }

                        localDataSource.insertUsers(cache)

                        val dto = mapNullInputList(fromNetwork) { it.toDto() }

                        emit(Resource.Success(dto))
                    }
                    is FromNetwork.Error -> {
                        emit(Resource.Error(networkState.message))
                    }
                }
            }
        }
    }

}.flowOn(ioDispatcher)
c
Fixed the rotation for anyone that needs it. 🙃
g
Not much better honestly 😬
also looks that it just a part of code
o
Need a better picture ?
Copy code
override fun getUsersSearch(username: String) = flow<Resource<List<UserDTO>>> {
    emit(Resource.Loading())

    localDataSource.getUserSearch(username).collect { fromDb ->
        when (fromDb) {
            is FromDb.Success -> {
                val dtos = mapNullInputList(fromDb.data) { it.toDto() }
                emit(Resource.Success(dtos))
            }
            is FromDb.Empty -> {
                when (val networkState = remoteDataSource.getUserSearch(username)) {
                    is FromNetwork.Success -> {
                        val fromNetwork = networkState.body

                        val cache = mapNullInputList(fromNetwork) { it.toEntity() }

                        localDataSource.insertUsers(cache)

                        val dto = mapNullInputList(fromNetwork) { it.toDto() }

                        emit(Resource.Success(dto))
                    }
                    is FromNetwork.Error -> {
                        emit(Resource.Error(networkState.message))
                    }
                }
            }
        }
    }

}.flowOn(ioDispatcher)
g
how do you detect this memory leak?
A small general note I have feeling that implementation would be better if you do:
Copy code
localDataSource.getUserSearch(username)
   .map. { fromDb -> ... }
   .onStart { emit(Resource.Loading()) }
It looks more natural for me and also doesn’t require flow builder at all
In general I don’t see any obviuous leaks in this code, but I don’t know how remoteDataSource.getUserSearch, localDataSource.insertUsers or any other external APIs are implemented, maybe the are blocking, but flow builder looks fine
o
Thank you for your answer
Copy code
// LocalDataSource
override suspend fun insertUsers(users: List<UserEntity>) = userDao.insertUsers(users)

// RemoteDataSource
override suspend fun getUserSearch(username: String): FromNetwork<List<UserResponse>> {
        return try {
            val response = apiService.getUsersSearch(username)
            return if (response.isSuccessful)
                FromNetwork.Success(body = response.body()?.items!!, message = response.message())
            else
                FromNetwork.Error(message = response.message())
        } catch (t: Throwable) {
            FromNetwork.Error(message = t.message)
        }
    }
i don't know how to check memory leak can you please tell me about it too
about the implementation, i think i will refactor it, it's nicer than my implementation
g
ah I got your question only know, so you are asking, will this code cause memory leak or not? I don’t see any obvious leaks, everything looks fine
o
i really appreaciate your answer thank you once again
g
https://kotlinlang.slack.com/archives/C0B8M7BUY/p1641797020029700?thread_ts=1641785081.026800&amp;cid=C0B8M7BUY Well, this still have the same problem for me, I cannot tell, it depends on apiService.getUsersSearch and userDao.insertUsers are implemented General rule, it will not cause leaks if those are suspend functions and not blocking (at least do not block for long period of time) So if you do not block and use suspend functions and structural concurrency it should be safe
o
For api service is from retrofit2 with suspend function and for dao is from dao with suspend function
👍 1