[Team-04][Android][Linus_Jay][3주차 금요일 여섯번째 PR]#285
[Team-04][Android][Linus_Jay][3주차 금요일 여섯번째 PR]#285cherrylime69 wants to merge 17 commits intocodesquad-members-2022:team-04from
Conversation
- 필터된 이슈 목록 리스트가 빈값이 아닐 때만 이슈 목록이 갱신되도록 수정
1. 네트워크 O -> 리모트에서 로컬에 캐시해줌, 로컬에서 내려주기 2. 네트워크 X -> 로컬에서 내려주기
- sealed class 를 생성하여 실제 issue 와 progress bar 구분 - ProgressBar ViewType 타입 할당 - Is 연산자를 활용하여 sealed class 구분 - firebase의 limit 과 startAfter 메서드를 활용하여 페이징 처리
- 코루틴 수정 : Coroutine() -> suspend 함수인 coroutine() 으로 수정하고 .join() 을 삭제 - suspend 함수가 아닌 Coroutine 에서 선언된 launch 실행문들은 무시되고 함수를 리턴 함 , 최초에는 join 이 있어서 문제가 없었음 - 컨벤션에 맞게 변수이름 수정
- 맨 마지막 스크롤까지 가면 page 숫자 증가 - page 숫자를 가지고 페이징 처리 구현
caching 적용 및 네트워크상태 관리
페이징 처리를 하여 이슈 목록 화면 표시 구현
[Team-04][Linus_Jay] Upstream에 마지막 PR 요청을 위한 PR
질문 답변
안녕하세요 ~ // line: 70
// 데이터를 추가하는 코드
// fireStore.collection(FIREBASE_COLLECTION_ISSUE_PATH).document().set(it1)
lastVisibleDocument = issueData.documents.last()
Log.d("reno", "[loadNextPageIssues] last visible document id: ${lastVisibleDocument?.id}")
Log.d("reno", "[loadNextPageIssues] last visible document id: ${(list.last() as Issue).title}")
Log.d("reno", "[loadNextPageIssues] last visible document id: ${(list.last() as Issue).description}")
------------------------------------------------ Log ------------------------------------------------
//첫번째 loadNextPageIssues 함수가 호출되었을 때 결과
9799-9799/com.example.issu_tracker D/reno: [loadNextPageIssues] last visible document id: 1PM0sqRmEzgwngIKNdV4
9799-9799/com.example.issu_tracker D/reno: [loadNextPageIssues] last visible document id: 제이 야근 그만
9799-9799/com.example.issu_tracker D/reno: [loadNextPageIssues] last visible document id: 테스트입니다 |
| sealed class IssueList : Serializable { | ||
|
|
||
| object IssueProgressBar : IssueList() | ||
|
|
||
| @Entity | ||
| data class Issue( | ||
| @ColumnInfo(name = "issue_id") | ||
| var id: String, | ||
| val comments: List<Comment>, | ||
| val description: String, | ||
| val label: List<Label>, | ||
| val mileStone: String, | ||
| val state: Boolean, | ||
| val title: String, | ||
| @Embedded | ||
| val user: User | ||
| ) : IssueList(), Serializable { | ||
| @PrimaryKey(autoGenerate = true) | ||
| var idx: Int = 0 | ||
| } | ||
| } |
| class Error<T : Any>(val code: Int = EMPTY) : NetworkResult<T>() | ||
| class Exception<T : Any>(val e: Throwable) : NetworkResult<T>() |
There was a problem hiding this comment.
Error 와 Exception 을 구분하셨던 이유가 있나요?? (궁금해서요 ㅎㅎ)
| friendData.forEach { | ||
| val user = | ||
| User( | ||
| it["uid"] ?: "", it["name"] ?: "", | ||
| it["userPhoto"] ?: "" | ||
| ) | ||
| friendList.add(user) | ||
| } |
| issueData.documents.forEach { | ||
| val issueObj = it.toObject(IssueDto::class.java) | ||
| issueObj?.id = it.id | ||
| issueObj?.let { issueDto -> | ||
| issueDto.toIssue()?.let { issue -> | ||
| list.add(issue) | ||
| } | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
여기도 map 연산자와 toList 연산자를 잘 사용한다면 가독성있는 코드를 만들 수 있겠네요~
| @Database(entities = [User::class , IssueList.Issue::class ], version = 2,exportSchema = false) | ||
| @TypeConverters(Converters::class) | ||
| abstract class IssueTrackerDatabase : RoomDatabase() { | ||
| abstract fun userDao(): UserDao | ||
| abstract fun issueDao(): IssueDao | ||
| } No newline at end of file |
There was a problem hiding this comment.
Use, Issue 정보를 Disk 에 저장하는 이유가 있나용?
Memory 에 저장해도 되지 않았나 싶네요 ㅎㅎ
| if (issueListResponse is NetworkResult.Success) { | ||
| val issueList = issueListResponse.data.toMutableList() | ||
| issueList.removeLast() | ||
| issueList.addAll(repository.loadNextPageIssues(currentPage)) | ||
| issueList.add(IssueList.IssueProgressBar) | ||
| _issueListStateFlow.value = NetworkResult.Success(issueList) | ||
| } |
There was a problem hiding this comment.
NetworkResult.Success 를 제외한 나머지 경우들은 처리 안하는 이유가 있나요?
| .filter { | ||
| if (condition.state.isNotEmpty() && it is IssueList.Issue) { | ||
| it.state | ||
| } else { | ||
| true | ||
| } | ||
| }.filter { | ||
| if (condition.writer.isNotEmpty() && it is IssueList.Issue) { | ||
| it.user.name == condition.writer | ||
| } else { | ||
| true | ||
| } | ||
| } | ||
| .filter { | ||
| if (it is IssueList.Issue) { | ||
| it.label.any { label -> | ||
| if (condition.label.isNotEmpty()) { | ||
| label.content == condition.label | ||
| } else { | ||
| true | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
하나의 filter 연산자에서 처리할 수 있지 않나용?
나눠서 처리하는 이유가 있나요??
고생 많았어요~ |
🤷♂️ Description
📷 Screenshots
캐싱 구현 영상
2022-07-01.9.07.05.mov
무한 스크롤 구현 영상
2022-07-01.9.08.39.mov
🎉 질문 사항
안녕하세요 레노! 페이징 처리를 위해 firebase 의 limit 과 startAfter 메서드를 사용하고 있습니다. (참고자료)
첫번째 페이징 처리로 10개의 데이터를 먼저 불러오고 맨 마지막으로 스크롤할 때
loadNextPageIssues가 호출되는 구조입니다.첫번째로 데이터를 불러오고 10번째의 데이터를
lastVisibleDocument에 저장하고loadNextPageIssues가 호출될 때,startAfter(lastVisibleDocument)를 사용하여 11번째 데이터부터 다시 10개의 데이터를 불러오도록 구현을 원했습니다.하지만 어찌된 일인지,
lastVisibleDocument값은 정상적으로 존재하는데, 자꾸issueData가 빈 리스트로 값이 반환됩니다. (밑에 에러 코드 첨부)원인을 도저히 찾지 못해 어쩔 수 없이, page 번호를 fragment -> ViewModel -> repository 까지 불러와
lastVisibleDoc에서 볼 수 있듯이 10번째 데이터 값(20번째, 30번째, 40번째 등등)을 다시 할당하고 이를 startAfter() 인자로 넘겨주는 방식으로 구현을 완료했습니다. 하지만 이 경우, 페이지 번호가 높을수록 불러오는 데이터양이 많아져 성능이 저하될 수 밖에 없는 단점이 있습니다. (즉, 지금은 그냥 임시방편으로 페이징을 구현하고 있습니다.)혹시 이에 대해 조언이 있을까요?
🎃 기타