Skip to content

Commit 19839da

Browse files
authored
๐Ÿ”€ #72 from boostcampwm-2022/feat/postToNotReactive
๊ฒŒ์‹œ๊ธ€ ํƒญ Reactive ์ฒ˜๋ฆฌ ๋Œ€์‹  ํŽ˜์ด์ง•์ฒ˜๋ฆฌ๋กœ ๋ณ€๊ฒฝ
2 parents 67aa878 + c845429 commit 19839da

File tree

14 files changed

+370
-55
lines changed

14 files changed

+370
-55
lines changed

โ€Ždata/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,7 @@ dependencies {
6060
implementation "androidx.room:room-runtime:$roomVersion"
6161
annotationProcessor "androidx.room:room-compiler:$roomVersion"
6262
kapt "androidx.room:room-compiler:$roomVersion"
63+
64+
// Paging3
65+
implementation "androidx.paging:paging-runtime:$paging3Version"
6366
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package com.whyranoid.data.post
2+
3+
import androidx.paging.PagingSource
4+
import androidx.paging.PagingState
5+
import com.google.firebase.firestore.FirebaseFirestore
6+
import com.google.firebase.firestore.QuerySnapshot
7+
import com.whyranoid.data.constant.CollectionId
8+
import com.whyranoid.data.constant.FieldId
9+
import com.whyranoid.data.constant.FieldId.AUTHOR_ID
10+
import com.whyranoid.data.model.GroupInfoResponse
11+
import com.whyranoid.data.model.RecruitPostResponse
12+
import com.whyranoid.data.model.RunningPostResponse
13+
import com.whyranoid.data.model.UserResponse
14+
import com.whyranoid.data.model.toGroupInfo
15+
import com.whyranoid.data.model.toUser
16+
import com.whyranoid.domain.model.Post
17+
import com.whyranoid.domain.model.RecruitPost
18+
import com.whyranoid.domain.model.RunningHistory
19+
import com.whyranoid.domain.model.RunningPost
20+
import com.whyranoid.domain.model.toRule
21+
import kotlinx.coroutines.tasks.await
22+
import javax.inject.Inject
23+
import javax.inject.Singleton
24+
25+
@Singleton
26+
class MyPostPagingDataSource @Inject constructor(
27+
private val db: FirebaseFirestore
28+
) : PagingSource<QuerySnapshot, Post>() {
29+
30+
private lateinit var myUid: String
31+
32+
override fun getRefreshKey(state: PagingState<QuerySnapshot, Post>): QuerySnapshot? {
33+
TODO("Not yet implemented")
34+
}
35+
36+
override suspend fun load(params: LoadParams<QuerySnapshot>): LoadResult<QuerySnapshot, Post> {
37+
return try {
38+
val postList = mutableListOf<Post>()
39+
40+
// ํ˜„์žฌ ํŽ˜์ด์ง€
41+
val currentPage = params.key ?: db.collection(CollectionId.POST_COLLECTION)
42+
.whereEqualTo(AUTHOR_ID, myUid)
43+
.limit(DATA_COUNT_PER_PAGE)
44+
.get()
45+
.await()
46+
47+
// Post ํƒ€์ž… ์บ์ŠคํŒ…
48+
// TODO ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
49+
currentPage.forEach { document ->
50+
51+
if (document[FieldId.RUNNING_HISTORY_ID] != null) {
52+
document.toObject(RunningPostResponse::class.java).let { postResponse ->
53+
val authorResponse = db.collection(CollectionId.USERS_COLLECTION)
54+
.document(postResponse.authorId)
55+
.get()
56+
.await()
57+
.toObject(UserResponse::class.java)
58+
59+
authorResponse?.let {
60+
val runningHistory =
61+
db.collection(CollectionId.RUNNING_HISTORY_COLLECTION)
62+
.document(postResponse.runningHistoryId)
63+
.get()
64+
.await()
65+
.toObject(RunningHistory::class.java)
66+
67+
runningHistory?.let {
68+
postList.add(
69+
RunningPost(
70+
postId = postResponse.postId,
71+
author = authorResponse.toUser(),
72+
updatedAt = postResponse.updatedAt,
73+
runningHistory = it,
74+
likeCount = 0,
75+
content = postResponse.content
76+
)
77+
)
78+
}
79+
}
80+
}
81+
} else {
82+
document.toObject(RecruitPostResponse::class.java).let { postResponse ->
83+
val authorResponse = db.collection(CollectionId.USERS_COLLECTION)
84+
.document(postResponse.authorId)
85+
.get()
86+
.await()
87+
.toObject(UserResponse::class.java)
88+
89+
authorResponse?.let {
90+
val groupInfoResponse = db.collection(CollectionId.GROUPS_COLLECTION)
91+
.document(postResponse.groupId)
92+
.get()
93+
.await()
94+
.toObject(GroupInfoResponse::class.java)
95+
96+
groupInfoResponse?.let {
97+
val author = authorResponse.toUser()
98+
postList.add(
99+
RecruitPost(
100+
postId = postResponse.postId,
101+
author = author,
102+
updatedAt = postResponse.updatedAt,
103+
groupInfo = groupInfoResponse
104+
.toGroupInfo(
105+
author,
106+
rules = groupInfoResponse.rules.map {
107+
it.toRule()
108+
}
109+
)
110+
)
111+
)
112+
}
113+
}
114+
}
115+
}
116+
}
117+
118+
// ๋งˆ์ง€๋ง‰ ์Šค๋ƒ…์ƒท ์ €์žฅ
119+
val lastDocumentSnapshot = currentPage.documents[currentPage.size() - 1]
120+
121+
// ๋งˆ์ง€๋ง‰ ์Šค๋ƒ…์ƒท ์ดํ›„ ํŽ˜์ด์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
122+
val nextPage = db.collection(CollectionId.POST_COLLECTION)
123+
.whereEqualTo(AUTHOR_ID, myUid)
124+
.limit(DATA_COUNT_PER_PAGE)
125+
.startAfter(lastDocumentSnapshot)
126+
.get()
127+
.await()
128+
129+
LoadResult.Page(
130+
data = postList,
131+
prevKey = null,
132+
nextKey = nextPage
133+
)
134+
} catch (e: Exception) {
135+
LoadResult.Error(e)
136+
}
137+
}
138+
139+
fun setMyUid(myUid: String) {
140+
this.myUid = myUid
141+
}
142+
143+
companion object {
144+
private const val DATA_COUNT_PER_PAGE = 10L
145+
}
146+
}

โ€Ždata/src/main/java/com/whyranoid/data/post/PostDataSourceImpl.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ class PostDataSourceImpl @Inject constructor(
3131
private val db: FirebaseFirestore
3232
) : PostDataSource {
3333

34-
// TODO : ์กฐ๊ธˆ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌ ํ•„์š”.
34+
// TODO : ์กฐ๊ธˆ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌ ํ•„์š”.
35+
// TODO : ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๊ฐ€ ์ž˜ ๋๋‚˜๋ฉด ์‚ญ์ œ
3536
override fun getAllPostFlow(): Flow<List<Post>> =
3637
callbackFlow {
3738
db.collection(CollectionId.POST_COLLECTION)
@@ -124,17 +125,18 @@ class PostDataSourceImpl @Inject constructor(
124125
awaitClose()
125126
}
126127

128+
// TODO : ํŽ˜์ด์ง• ์ฒ˜๋ฆฌ๊ฐ€ ์ž˜ ๋๋‚˜๋ฉด ์‚ญ์ œ
127129
override fun getMyPostFlow(uid: String): Flow<List<Post>> =
128130
callbackFlow {
129131
db.collection(CollectionId.POST_COLLECTION)
130132
.whereEqualTo(AUTHOR_ID, uid)
131133
.orderBy(UPDATED_AT, Query.Direction.DESCENDING)
132134
.addSnapshotListener { snapshot, _ ->
133135
val postList = mutableListOf<Post>()
134-
snapshot?.forEach { docuemnt ->
136+
snapshot?.forEach { document ->
135137

136-
if (docuemnt[RUNNING_HISTORY_ID] != null) {
137-
docuemnt.toObject(RunningPostResponse::class.java).let { postResponse ->
138+
if (document[RUNNING_HISTORY_ID] != null) {
139+
document.toObject(RunningPostResponse::class.java).let { postResponse ->
138140
db.collection(CollectionId.USERS_COLLECTION)
139141
.document(postResponse.authorId)
140142
.get()
@@ -171,7 +173,7 @@ class PostDataSourceImpl @Inject constructor(
171173
}
172174
}
173175
} else {
174-
docuemnt.toObject(RecruitPostResponse::class.java).let { postResponse ->
176+
document.toObject(RecruitPostResponse::class.java).let { postResponse ->
175177

176178
db.collection(CollectionId.USERS_COLLECTION)
177179
.document(postResponse.authorId)
@@ -251,14 +253,12 @@ class PostDataSourceImpl @Inject constructor(
251253

252254
val previousRecruitPostId =
253255
previousRecruitPost.toObjects(RecruitPostResponse::class.java).first().postId
256+
254257
db.collection(CollectionId.POST_COLLECTION)
255258
.document(previousRecruitPostId)
256-
.set(
257-
RecruitPostResponse(
258-
postId = postId,
259-
authorId = authorUid,
260-
updatedAt = System.currentTimeMillis(),
261-
groupId = groupUid
259+
.update(
260+
mapOf(
261+
UPDATED_AT to System.currentTimeMillis()
262262
)
263263
).addOnSuccessListener {
264264
cancellableContinuation.resume(true)
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package com.whyranoid.data.post
2+
3+
import androidx.paging.PagingSource
4+
import androidx.paging.PagingState
5+
import com.google.firebase.firestore.FirebaseFirestore
6+
import com.google.firebase.firestore.Query
7+
import com.google.firebase.firestore.QuerySnapshot
8+
import com.whyranoid.data.constant.CollectionId
9+
import com.whyranoid.data.constant.CollectionId.POST_COLLECTION
10+
import com.whyranoid.data.constant.FieldId.RUNNING_HISTORY_ID
11+
import com.whyranoid.data.constant.FieldId.UPDATED_AT
12+
import com.whyranoid.data.model.GroupInfoResponse
13+
import com.whyranoid.data.model.RecruitPostResponse
14+
import com.whyranoid.data.model.RunningPostResponse
15+
import com.whyranoid.data.model.UserResponse
16+
import com.whyranoid.data.model.toGroupInfo
17+
import com.whyranoid.data.model.toUser
18+
import com.whyranoid.domain.model.Post
19+
import com.whyranoid.domain.model.RecruitPost
20+
import com.whyranoid.domain.model.RunningHistory
21+
import com.whyranoid.domain.model.RunningPost
22+
import com.whyranoid.domain.model.toRule
23+
import kotlinx.coroutines.tasks.await
24+
import javax.inject.Inject
25+
import javax.inject.Singleton
26+
27+
@Singleton
28+
class PostPagingDataSource @Inject constructor(
29+
private val db: FirebaseFirestore
30+
) : PagingSource<QuerySnapshot, Post>() {
31+
32+
override fun getRefreshKey(state: PagingState<QuerySnapshot, Post>): QuerySnapshot? {
33+
TODO("Not yet implemented")
34+
}
35+
36+
override suspend fun load(params: LoadParams<QuerySnapshot>): LoadResult<QuerySnapshot, Post> {
37+
return try {
38+
val postList = mutableListOf<Post>()
39+
// ํ˜„์žฌ ํŽ˜์ด์ง€
40+
val currentPage = params.key ?: db.collection(POST_COLLECTION)
41+
.orderBy(UPDATED_AT, Query.Direction.DESCENDING)
42+
.limit(DATA_COUNT_PER_PAGE)
43+
.get()
44+
.await()
45+
46+
// Post ํƒ€์ž… ์บ์ŠคํŒ…
47+
// TODO ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
48+
currentPage.forEach { document ->
49+
50+
if (document[RUNNING_HISTORY_ID] != null) {
51+
document.toObject(RunningPostResponse::class.java).let { postResponse ->
52+
val authorResponse = db.collection(CollectionId.USERS_COLLECTION)
53+
.document(postResponse.authorId)
54+
.get()
55+
.await()
56+
.toObject(UserResponse::class.java)
57+
58+
authorResponse?.let {
59+
val runningHistory =
60+
db.collection(CollectionId.RUNNING_HISTORY_COLLECTION)
61+
.document(postResponse.runningHistoryId)
62+
.get()
63+
.await()
64+
.toObject(RunningHistory::class.java)
65+
66+
runningHistory?.let {
67+
postList.add(
68+
RunningPost(
69+
postId = postResponse.postId,
70+
author = authorResponse.toUser(),
71+
updatedAt = postResponse.updatedAt,
72+
runningHistory = it,
73+
likeCount = 0,
74+
content = postResponse.content
75+
)
76+
)
77+
}
78+
}
79+
}
80+
} else {
81+
document.toObject(RecruitPostResponse::class.java).let { postResponse ->
82+
val authorResponse = db.collection(CollectionId.USERS_COLLECTION)
83+
.document(postResponse.authorId)
84+
.get()
85+
.await()
86+
.toObject(UserResponse::class.java)
87+
88+
authorResponse?.let {
89+
val groupInfoResponse = db.collection(CollectionId.GROUPS_COLLECTION)
90+
.document(postResponse.groupId)
91+
.get()
92+
.await()
93+
.toObject(GroupInfoResponse::class.java)
94+
95+
groupInfoResponse?.let {
96+
val author = authorResponse.toUser()
97+
postList.add(
98+
RecruitPost(
99+
postId = postResponse.postId,
100+
author = author,
101+
updatedAt = postResponse.updatedAt,
102+
groupInfo = groupInfoResponse
103+
.toGroupInfo(
104+
author,
105+
rules = groupInfoResponse.rules.map {
106+
it.toRule()
107+
}
108+
)
109+
)
110+
)
111+
}
112+
}
113+
}
114+
}
115+
}
116+
117+
// ๋งˆ์ง€๋ง‰ ์Šค๋ƒ…์ƒท ์ €์žฅ
118+
val lastDocumentSnapshot = currentPage.documents[currentPage.size() - 1]
119+
120+
// ๋งˆ์ง€๋ง‰ ์Šค๋ƒ…์ƒท ์ดํ›„ ํŽ˜์ด์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
121+
val nextPage = db.collection(POST_COLLECTION)
122+
.orderBy(UPDATED_AT, Query.Direction.DESCENDING)
123+
.limit(DATA_COUNT_PER_PAGE).startAfter(lastDocumentSnapshot)
124+
.get()
125+
.await()
126+
127+
LoadResult.Page(
128+
data = postList,
129+
prevKey = null,
130+
nextKey = nextPage
131+
)
132+
} catch (e: Exception) {
133+
LoadResult.Error(e)
134+
}
135+
}
136+
137+
companion object {
138+
private const val DATA_COUNT_PER_PAGE = 10L
139+
}
140+
}

โ€Ždata/src/main/java/com/whyranoid/data/post/PostRepositoryImpl.kt

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
11
package com.whyranoid.data.post
22

3+
import androidx.paging.Pager
4+
import androidx.paging.PagingConfig
5+
import androidx.paging.PagingData
36
import com.whyranoid.domain.model.Post
47
import com.whyranoid.domain.repository.PostRepository
58
import kotlinx.coroutines.flow.Flow
69
import javax.inject.Inject
710

811
class PostRepositoryImpl @Inject constructor(
9-
private val postDataSource: PostDataSource
12+
private val postDataSource: PostDataSource,
13+
private val postPagingDataSource: PostPagingDataSource,
14+
private val myPostPagingDataSource: MyPostPagingDataSource
1015
) : PostRepository {
1116

12-
// TODO : ํŽ˜์ด์ง•์ฒ˜๋ฆฌํ•˜๊ธฐ
13-
override fun getPagingPosts(): Flow<List<Post>> {
14-
TODO("Not yet implemented")
17+
// TODO : ์บ์‹ฑํ•˜๊ธฐ
18+
override fun getPagingPosts(): Flow<PagingData<Post>> {
19+
return Pager(
20+
PagingConfig(pageSize = 5)
21+
) {
22+
postPagingDataSource
23+
}.flow
24+
}
25+
26+
override fun getMyPagingPosts(uid: String): Flow<PagingData<Post>> {
27+
myPostPagingDataSource.setMyUid(uid)
28+
return Pager(
29+
PagingConfig(pageSize = 5)
30+
) {
31+
myPostPagingDataSource
32+
}.flow
1533
}
1634

1735
override fun getAllPostFlow(): Flow<List<Post>> {

0 commit comments

Comments
ย (0)