I have a question about how to use the mutex. In t...
# android-architecture
t
I have a question about how to use the mutex. In this document, they use mutex like this. In this way, we can not prevent duplicating network requests. How about wrapping whole the function? Or do you have any other recommendations?
Copy code
suspend fun getLatestNews(refresh: Boolean = false): List<ArticleHeadline> {
        if (refresh || latestNews.isEmpty()) {
            val networkResult = newsRemoteDataSource.fetchLatestNews()
            // Thread-safe write to latestNews
            latestNewsMutex.withLock {
                this.latestNews = networkResult
            }
        }

        return latestNewsMutex.withLock { this.latestNews }
    }
Source: https://developer.android.com/topic/architecture/data-layer#cache_the_result_of_the_network_request
Copy code
suspend fun getLatestNews(refresh: Boolean = false): List<ArticleHeadline> {
        return latestNewsMutex.withLock {
            if (refresh || latestNews.isEmpty()) {
                val networkResult = newsRemoteDataSource.fetchLatestNews()
                this.latestNews = networkResult
            }
            this.latestNews
        }
    }
The tradeoff is that if a network request takes 10 seconds, and then 5 seconds later you start executing a second request, and the second request references a different cache key, the block will take 20 seconds. However, I believe it is better to enclose the request in a mutex in the basic pattern.
c
What do you wanna achieve?
t
Currently, what I would like to achieve is to eliminate duplicate requests.
m
You can control it manually. Like you said, the mutex would affect non-related requests.
For example, in my last position I had a network layer being called from separate processes. So requests could be duplicated, which had to be avoided, but at the same time, other request had to be sent without delay
So, instead of mutex & methods with return types, I created asynchronous methods with a centralized collection of callbacks & a collection of "active" requests. With that, every time you call the requests methods, you can just ask "are we already requesting this? if so, just add this extra callback to the pile. Otherwise, add the callback & start the request".
Now, you could simplify your scenario by using an observable, like Flow or LiveData. That way , instead of requesting data & potentially duplicating network petitions, your app just listens to updates from the data source. At that point you can set up a delay to fire network requests & refresh the data, or manual triggers, like a pull, or both
Generally speaking, most of the time, you'll want I/O to be fully asynchronous. No matter what you use, just don't wait for things to happen, let them tell you when they happen.
j
There are cases where your async operations rely on a single resource, e.g. trading a refresh token. There you need to make sure not multiple network requests 'recover' simultaneously.
In that case just make sure to not accidentally mix java threading and coroutines Synchronisation, e.g semaphores, synchronized or reenteantlock. Mutex seemed to work. Just don't use the same mutex at different places to avoid deadlocks.