Android

코루틴 좋아요 동기화 처리

그란. 2022. 11. 7. 15:11

사용자가 컨텐츠에 대해 좋아요 했을때 

컨텐츠가 보이는 어떤 화면에서든 이벤트를 받아와 UI 업데이트 하려고 한다. 

 

 

1. 도메인 모듈에 인터페이스 모델 추가 

sealed interface ContentEvent {
    data class AddLike(
        val id: Int
    ) : ContentEvent

    data class RemoveLike(
        val id: Int
    ) : ContentEvent
}

 

레포지토리에 SharedFlow 생성 

interface ContentRepository {
    val contentEvent: SharedFlow<ContentEvent>
}

 

internal class ContentRepositoryImpl @Inject constructor(
    private val remote: ContentRemoteDataSource,
) : ContentRepository {

    private val _contentEvent: MutableSharedFlow<ContentEvent> = MutableSharedFlow()
    override val contentEvent = _contentEvent.asSharedFlow()
    
    
    override suspend fun updateLike(id: Int): Result<Boolean> {
        return remote.updateLike(id).onSuccess { isLiked ->
            if (isLiked) {
                _contentEvent.emit(ContentEvent.AddLike(id))
            } else {
                _contentEvent.emit(ContentEvent.RemoveLike(id))
            }
        }
    }
    
}

API 통신이 성공하면 contentEvent에 전파 ( isLiked 는 서버 Response ) 

 

 

UseCase

@Singleton
class FetchContentEventUseCase @Inject constructor(
    private val repository: ContentRepository
) {
    operator fun invoke() = repository.contentEvent
}

 

 

컨텐츠가 보이는 뷰모델들에 대해 해당 UseCase Inject

fetchCommentEventUseCase: FetchCommentEventUseCase

 

init{
	fetchContentEventUseCase.invoke()
            .onEach {
                when (it) {
                    is ContentEvent.AddLike -> {
                        fetchLike(it.id, true)
                    }
                    is ContentEvent.RemoveLike -> {
                        fetchLike(it.id, false)
                    }
                }
            }.launchIn(viewModelScope)
}
private fun fetchLike(id: Int, isLike: Boolean) = launch {
    updateState {
        copy(
            contents = this.contents.edit {
                val index = indexOfFirst { it.id == id }.takeIf { it > -1 } ?: return@edit
                val content = this[index]
                this[index] = content.copy(
                    isLike = isLike,
                    likeCount = if (isLike) content.likeCount + 1 else content.likeCount - 1
                )
            })
    }
}

그 다음 리스트를 변경해주면 된다.