-
Notifications
You must be signed in to change notification settings - Fork 0
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
4주차 세미나 과제 #9
4주차 세미나 과제 #9
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
채연 언니 코드는 항상 배울 점이 많아용
fun toFollower() = data.map { follower -> | ||
Follower( | ||
id = follower.id, | ||
name = "${follower.firstName} ${follower.lastName}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 이렇게도 할 수 있구낭..!
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class BaseResponse<T>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
우와..! 이거 정말 짱이네용
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
와 이거 쇽샥해도 되나요 ? ㅋㅋ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
배웠습니다 ㅎㅎ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
와 이거 쇽샥해도 되나요 ? ㅋㅋ
저희 다 오픈소스잖아요 🤭
|
||
fun toFollower() = data.map { follower -> | ||
Follower( | ||
id = follower.id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DiffUtill에서 아이템을 비교할 때 혹시 명확한 식별을 위해서 id도 가져오는건가용? (뭔가 나의 말이 이상한데......)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
넵 areItemsTheSame
에서 id 값을 비교해주고 싶어서 가져왔습니다!
val followerList: List<Follower>? | ||
get() = _followerList.value | ||
|
||
private val _getFollowerListState = MutableLiveData<RemoteUiState>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거 좀 멍청 질문일 수도 있는데 UiState 의 장점은 뭔가영?!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UiState와 같은 클래스를 활용하면 ViewModel에서 수행한 결과(Success, Failure, Error, Loading 등등)에 따라 View에서 적절한 UI 처리를 할 수 있습니다! 효율적인 UI 처리가 가능하고 ViewModel과 View의 역할을 명확하게 구분할 수 있어서 좋은 것 같아요
NowInAndroid 프로젝트에서 이런 Ui 상태 처리를 잘 구현해둔 것 같은데 한번 참고해보셔도 좋을 것 같습니다 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드 조금 더 자세히 살펴보고 리뷰 추가하겠습니다! 과제하느라 고생하셨어요!
@SerialName("message") | ||
val message: String, | ||
@SerialName("data") | ||
val data: T? = null, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오오오 Response에서 data의 타입만 달라지니까 제네릭으로 만들 수 있군요! 한수 배워갑니다👍👍
suspend fun postSignIn( | ||
@Body requestPostSignInDto: RequestPostSignInDto, | ||
): BaseResponse<ResponsePostSignInDto> | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 함수명이랑 Dto 클래스명에 어떤 HTTP 메서드를 사용하는지 명시해주니까 더 좋은 거 같아요!
@Module | ||
@InstallIn(SingletonComponent::class) | ||
object RetrofitModule { | ||
private const val APPLICATION_JSON = "application/json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아맞다 상수화! 리팩토링 때 반영하겠습니다ㅎㅎ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
훨씬 깔끔하네유
|
||
@Provides | ||
@Singleton | ||
@Retrofit2(BaseUrlType.SOPT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오.. base url 타입을 어노테이션으로도 지정할 수 있네요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
장인이시네요 👏 오늘도 배워갑니당 짱짱
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class BaseResponse<T>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
와 이거 쇽샥해도 되나요 ? ㅋㅋ
) : FollowerRepository { | ||
override suspend fun getFollowerList(page: Int): Result<List<Follower>> = | ||
runCatching { | ||
followerDataSource.getFollowerList(page).toFollower() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 처음부터 api url 에 page 숫자를 명시해준게 아닌, 인자로 받아서 여러 페이지 접근할 수 있도록 해주셨군요 짱이십니다 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
22
|
||
override fun onDestroyView() { | ||
super.onDestroyView() | ||
followerAdapter = null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null 초기화 해준 후에 뷰를 소멸시키는게 메모리 누수 방지에 좋을 것 같습니당
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onDestroyView
는 뷰모로부터 뷰가 제거되기 전에 호출(Internally it is called after the view's state has been saved but before it has been removed from its parent.)되어서 뷰가 파괴된 후에 메모리가 누수되지 않도록 종속적인 자원을 해제하는 역할을 한다고 이해하고 공식문서와 같은 형식으로 작성해보았는데, super.onDestroyView()를 호출하기 전에 자원을 해제하지 않았을 때 메모리가 누수되는 경우가 있을까요?
.onFailure { t -> | ||
if (t is HttpException) { | ||
when (t.code()) { | ||
CODE_INVALID_INPUT -> _signupState.value = Failure(CODE_INVALID_INPUT) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여러 경우에 대비해서 예외 처리해주신 부분 굉장히 섬세하시네요 👏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋은코드 잘 배워갑니다 ㅎㅎ State를 잘활용하시네요! 저도 배우겠습니다 ㅎ
import kotlinx.serialization.Serializable | ||
|
||
@Serializable | ||
data class BaseResponse<T>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
배웠습니다 ㅎㅎ
@Qualifier | ||
annotation class Retrofit2(val baseUrlType: BaseUrlType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 좋은 방법이네요!
|
||
_followerList.value = response | ||
_getFollowerListState.value = Success | ||
Timber.d("GET FOLLOWER LIST SUCCESS : $response") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
로그찍는 습관 좋네요 !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
눈물과 더불어 빵을 먹어 보지 않은 자는 인생의 참다운 맛을 모른다. -괴테
) : AuthRepository { | ||
override suspend fun postSignup(requestPostSignUpDto: RequestPostSignUpDto): Result<ResponsePostSignUpDto?> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Result 타입을 사용한 이유가 궁금합니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좀 더 간결하게 이벤트를 처리하기 위해 runCatching을 활용해서 반환 타입을 Result로 지정해주었습니당
) : FollowerRepository { | ||
override suspend fun getFollowerList(page: Int): Result<List<Follower>> = | ||
runCatching { | ||
followerDataSource.getFollowerList(page).toFollower() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
22
@Module | ||
@InstallIn(SingletonComponent::class) | ||
object RetrofitModule { | ||
private const val APPLICATION_JSON = "application/json" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
훨씬 깔끔하네유
val pwd = MutableLiveData("") | ||
val _id = MutableLiveData("") | ||
private val id: String | ||
get() = _id.value?.trim() ?: "" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
센스 좋네요
if (t is HttpException) { | ||
when (t.code()) { | ||
CODE_INVALID_INPUT -> _loginState.value = Failure(CODE_INVALID_INPUT) | ||
else -> _loginState.value = Error | ||
} | ||
Timber.e("POST SIGNIN FAIL ${t.code()} : ${t.message()}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고급지네요
else -> throw ClassCastException( | ||
parent.context.getString( | ||
R.string.view_type_error_msg, | ||
viewType, | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
섬세하네요
override fun getItemCount(): Int { | ||
return super.getItemCount() + HEADER_COUNT | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
새롭네요
private fun initRecyclerViewLayoutManager() { | ||
val layoutManager = GridLayoutManager(activity, 2) | ||
layoutManager.spanSizeLookup = object : SpanSizeLookup() { | ||
override fun getSpanSize(position: Int): Int { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 함수가 뭐였죠 하하 기억이 안나네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
position에 해당하는 아이템이 gridLayout에서 몇 개의 폭을 차지하는지 반환해주는 함수입니다!
Header는 화면 너비를 꽉 채우고 싶어서 override 했습니다
@@ -4,14 +4,28 @@ import android.widget.ImageView | |||
import androidx.databinding.BindingAdapter | |||
import coil.load | |||
import coil.transform.RoundedCornersTransformation | |||
import org.android.go.sopt.R | |||
|
|||
object BindingAdapter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
object 로 생성하신 이유가 궁금합니따이
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BindingAdapter 함수들은 프로젝트 전역에서 사용될 것이기 때문에 싱글톤 패턴으로 구현하는 것이 적합할 것 같아 object로 생성했습니다!
⛳️ Work Description
Essential
Advanced
📸 Screenshot
Sign up
Android.Emulator.-.Galaxy_S21_API_31_5554.2023-05-13.01-52-18.mp4
Log in & Follower
Android.Emulator.-.Galaxy_S21_API_31_5554.2023-05-13.01-52-56.mp4
📢 To Reviewers