티스토리 뷰
Android developer site 에서는 아래와 같이 몇가지 코루틴에 대해 권고하고 있다.
선요약 하자면,
1. Repository 에서 coroutine dispatcher 를 하드코딩 하지 마라.
2. suspend fun 는 기본 스레드에서 호출하기에 안전해야 함.
3. 비즈니스 및 데이터 레이어에서 코루틴 만들기
Repository 에서 coroutine dispatcher 를 하드코딩 하지 마라.
// OK
class NewsRepository(
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
suspend fun loadNews() = withContext(defaultDispatcher) { /* ... */ }
}
// DO NOT hardcode Dispatchers
class NewsRepository {
// DO NOT use Dispatchers.Default directly, inject it instead
suspend fun loadNews() = withContext(Dispatchers.Default) { /* ... */ }
}
Testable 한 코드를 만들기 위해, dispatcher 를 하드코딩 하는것이 아닌,
주입받아서 언제든지 TestDispathcer 로 바꿀 . 수있어야 함 .
suspend fun 는 기본 스레드에서 호출하기에 안전해야 함
class NewsRepository(private val ioDispatcher: CoroutineDispatcher) {
// httpUrlConnection 은 thread 를 blocking 하기 때문에, IO 스레드로 전환해야함.
suspend fun fetchLatestNews(): List<Article> {
withContext(ioDispatcher) { /* ... implementation ... */ }
}
}
.....
class GetLatestNewsWithAuthorsUseCase(
private val newsRepository: NewsRepository,
private val authorsRepository: AuthorsRepository
) {
// 단순히, newsRepository 에서 fetch 하는 내용이기 때문에, 해당 useCase 에서 스레드를 전환할 필요가 없음.
// 리스트를 생성하고 추가하는 가벼운 작업만 존재하기 때문에 Default Thread 에서도 큰 부담없음.
suspend operator fun invoke(): List<ArticleWithAuthor> {
val news = newsRepository.fetchLatestNews()
val response: List<ArticleWithAuthor> = mutableEmptyList()
for (article in news) {
val author = authorsRepository.getAuthor(article.author)
response.add(ArticleWithAuthor(article, author))
}
return Result.Success(response)
}
}
이정도는 안드로이드 개발자라면 당연히 다 알만한 내용.
비즈니스 및 데이터 레이어에서 코루틴 만들기
ViewModel 에서 코루틴을 만드는 것과는 별개로, Domain Layer 단에서 따로 코루틴을 만들 필요가 있는 경우.
두가지 케이스로 나뉠것이다.
1. 호출자의 scope 를 따라가는 경우 (호출자(대부분 viewModel) 가 파괴되면, 코루틴도 정지되어야 하는 경우)
class GetAllBooksAndAuthorsUseCase(
private val booksRepository: BooksRepository,
private val authorsRepository: AuthorsRepository,
) {
suspend fun getBookAndAuthors(): BookAndAuthors {
// 상위 호출자의 수명주기를 따라야 하는 경우
return coroutineScope {
val books = async { booksRepository.getAllBooks() }
val authors = async { authorsRepository.getAllAuthors() }
BookAndAuthors(books.await(), authors.await())
}
}
}
2. 호출자가 파괴 되더라도 작업은 끝마쳐야 하는 경우
이 경우는 반드시 결과를 전송해야 하는 backend 작업이 있을때 사용한다.
예를들면, 유저가 북마크 버튼을 누르고 화면을 바로 destory 시키는 것.
화면이 파괴되면서 북마크 job 이 cancel 되면 안되기 때문에 화면과 별개로 관리.
class ArticlesRepository(
private val articlesDataSource: ArticlesDataSource,
private val externalScope: CoroutineScope,
) {
// 이 경우는 externalScope (보통 Application 단위의 coroutine scope)을 사용.
// join 을 사용해 작업이 완료되는 것을 기다림
suspend fun bookmarkArticle(article: Article) {
externalScope.launch { articlesDataSource.bookmarkArticle(article) }
.join()
}
}
참조
https://developer.android.com/kotlin/coroutines/coroutines-best-practices?hl=ko
- Total
- Today
- Yesterday
- Kotlin
- IOS
- 깃헙
- 배열
- CentOS
- 안드로이드
- 앵커브리핑
- mysql
- 스위프트
- 리눅스
- GIT
- Android
- 점유율
- linux
- git hub
- xcode
- C
- 서버
- Phaser
- 노드
- nodejs
- Asterisk
- 손석희
- node.js
- php
- 뉴스룸
- BBC 가쉽
- C언어
- Node
- Swift
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |