Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Step4 - GitHub(인기 저장소) #32

Open
wants to merge 13 commits into
base: oyj7677
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@
- 로딩 UI를 노출할 때 CircularProgressIndicator를 활용한다.

## 기능 요구사항
- [] 목록이 로딩되기 전에는 로딩 UI를 노출한다.
- [] 목록이 빈 경우에는 빈 화면 UI를 노출한다.
- [] 오류가 발생한 경우 재시도 가능한 스낵바를 노출한다.
- [O] 목록이 로딩되기 전에는 로딩 UI를 노출한다.
- [O] 목록이 빈 경우에는 빈 화면 UI를 노출한다.
- [O] 오류가 발생한 경우 재시도 가능한 스낵바를 노출한다.

# Step 4 - GitHub(인기 저장소)

## 프로그래밍 요구사항
- domain 패키지를 만들어 비즈니스 로직을 캡슐화한다.
- 저장소의 Star 개수가 50개 이상인지 판단하는 로직도 도메인 레이어에 포함될지 스스로 판단한다.

## 기능 요구사항
- [O] 저장소의 Star 개수를 노출한다
- [O] 저장소의 Star 개수가 50개 이상이면 HOT 텍스트를 노출한다.

2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Github"
android:name="MainApplication"
android:name=".di.MainApplication"
tools:targetApi="31">
<activity
android:name=".MainActivity"
Expand Down
11 changes: 2 additions & 9 deletions app/src/main/java/nextstep/github/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,9 @@ import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import nextstep.github.ui.screen.github.GithubViewModel
import nextstep.github.ui.screen.github.MainScreen
import nextstep.github.ui.theme.GithubTheme

Expand All @@ -28,12 +25,8 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val snackbarHostState = remember { SnackbarHostState() }
MainScreen(
uiState = uiState,
snackbarHostState = snackbarHostState,
onClickSnackBar = { viewModel.getRepositories("next-step") }
viewModel = viewModel
)
}
}
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

16 changes: 0 additions & 16 deletions app/src/main/java/nextstep/github/core/model/RepositoryEntity.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package nextstep.github.data.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class GithubRepositoryData(
@SerialName("full_name") val fullName: String?,
@SerialName("description") val description: String?,
@SerialName("stargazers_count") val stars: Int?,
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package nextstep.github.core.network
package nextstep.github.data.network

sealed class ApiResult<out T> {
data class Success<out T>(val value: T) : ApiResult<T>()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package nextstep.github.core.network
package nextstep.github.data.network

import nextstep.github.core.model.RepositoryEntity
import nextstep.github.data.model.GithubRepositoryData
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path


interface GithubService {
@GET("orgs/{organization}/repos")
suspend fun getRepositories(@Path("organization") organization: String): Response<List<RepositoryEntity>>
suspend fun getRepositories(@Path("organization") organization: String): Response<List<GithubRepositoryData>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package nextstep.github.data.repository

import nextstep.github.data.model.GithubRepositoryData
import retrofit2.Response


interface GithubRepository {
suspend fun getRepositories(organization: String): Response<List<GithubRepositoryData>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package nextstep.github.data.repository

import nextstep.github.data.model.GithubRepositoryData
import nextstep.github.data.network.GithubService
import retrofit2.Response

class GithubRepositoryImpl(
private val githubService: GithubService
) : GithubRepository {

override suspend fun getRepositories(organization: String): Response<List<GithubRepositoryData>> {
return githubService.getRepositories(organization)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package nextstep.github.core.di
package nextstep.github.di

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import kotlinx.serialization.json.Json
import nextstep.github.core.data.GithubRepository
import nextstep.github.core.data.GithubRepositoryImpl
import nextstep.github.core.network.GithubService
import nextstep.github.data.repository.GithubRepository
import nextstep.github.data.repository.GithubRepositoryImpl
import nextstep.github.data.network.GithubService
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package nextstep.github
package nextstep.github.di

import android.app.Application
import nextstep.github.core.di.AppContainer

class MainApplication : Application() {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package nextstep.github.domain.entity

data class RepositoryEntity(
val fullName: String,
val description: String,
val stars: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package nextstep.github.domain.usecase

import nextstep.github.data.repository.GithubRepository
import nextstep.github.domain.entity.RepositoryEntity
import nextstep.github.data.network.ApiResult

class GetGithubRepoUseCase(
private val githubRepository: GithubRepository
) {
suspend operator fun invoke(organization: String): ApiResult<List<RepositoryEntity>> {
val response = githubRepository.getRepositories(organization)

return if (response.isSuccessful && response.body() != null) {
val repositoryEntityList = response.body()!!.map {
RepositoryEntity(
fullName = it.fullName ?: "",
description = it.description ?: "",
stars = it.stars ?: 0
)
}
ApiResult.Success(repositoryEntityList)
} else {
ApiResult.Error(response.code(), Throwable(response.message()))
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package nextstep.github
package nextstep.github.ui.screen.github

import android.util.Log
import androidx.lifecycle.ViewModel
Expand All @@ -11,13 +11,13 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import nextstep.github.core.data.GithubRepository
import nextstep.github.core.data.GithubRepositoryInfo
import nextstep.github.core.network.ApiResult
import nextstep.github.di.MainApplication
import nextstep.github.data.network.ApiResult
import nextstep.github.domain.usecase.GetGithubRepoUseCase
import nextstep.github.ui.screen.github.list.GithubRepositoryUiState

class GithubViewModel(
private val githubRepository: GithubRepository
private val getGithubRepoUseCase: GetGithubRepoUseCase
) : ViewModel() {

private val _uiState =
Expand All @@ -29,20 +29,14 @@ class GithubViewModel(

viewModelScope.launch(Dispatchers.IO) {
try {
when (val result = githubRepository.getRepositories(organization)) {
when (val result = getGithubRepoUseCase(organization)) {
is ApiResult.Success -> {
val githubRepositories = result.value.map {
GithubRepositoryInfo(
fullName = it.fullName ?: "",
description = it.description ?: ""
)
}
if (githubRepositories.isEmpty()) {
if (result.value.isEmpty()) {
_uiState.value = GithubRepositoryUiState.Empty
} else {
_uiState.value =
GithubRepositoryUiState.Success(
githubRepositories = githubRepositories
githubRepositories = result.value
)
}
}
Expand All @@ -67,7 +61,9 @@ class GithubViewModel(
.appContainer
.githubRepository

GithubViewModel(githubRepository)
val getGithubRepoUseCase = GetGithubRepoUseCase(githubRepository)

GithubViewModel(getGithubRepoUseCase)
}
}
}
Expand Down
Loading