Skip to content

Commit dbc911b

Browse files
authored
๐Ÿ”€ #43 from boostcampwm-2022/refactor/simpleThings
๊ฐ„๋‹จํ•œ ๋ฆฌํŒฉํ„ฐ๋ง, UiState ์ถ”๊ฐ€, ์ปค์Šคํ…€ Exception ์ถ”๊ฐ€
2 parents de2cd13 + 1dde8c6 commit dbc911b

File tree

11 files changed

+127
-94
lines changed

11 files changed

+127
-94
lines changed

โ€Ždata/src/main/java/com/whyranoid/data/group/GroupDataSource.kt

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,18 @@ import kotlinx.coroutines.suspendCancellableCoroutine
1515
import java.util.UUID
1616
import javax.inject.Inject
1717
import kotlin.coroutines.resume
18-
import kotlin.coroutines.suspendCoroutine
1918

2019
class GroupDataSource @Inject constructor(
2120
private val db: FirebaseFirestore
2221
) {
2322

24-
// TODO: suspendcancellablecoroutine๋กœ ๋ณ€๊ฒฝ
2523
suspend fun updateGroupInfo(
2624
groupId: String,
2725
groupName: String,
2826
groupIntroduce: String,
2927
rules: List<Rule>
3028
): Boolean {
31-
return suspendCoroutine { continuation ->
29+
return suspendCancellableCoroutine { cancellableContinuation ->
3230
db.collection(GROUPS_COLLECTION)
3331
.document(groupId)
3432
.update(
@@ -41,33 +39,31 @@ class GroupDataSource @Inject constructor(
4139
)
4240
)
4341
.addOnSuccessListener {
44-
continuation.resume(true)
42+
cancellableContinuation.resume(true)
4543
}
4644
.addOnFailureListener {
47-
continuation.resume(false)
45+
cancellableContinuation.resume(false)
4846
}
4947
}
5048
}
5149

52-
// TODO: suspendcancellablecoroutine๋กœ ๋ณ€๊ฒฝ
5350
suspend fun joinGroup(uid: String, groupId: String): Boolean {
54-
return suspendCoroutine<Boolean> { continuation ->
51+
return suspendCancellableCoroutine { cancellableContinuation ->
5552
db.collection(GROUPS_COLLECTION)
5653
.document(groupId)
5754
.update(
5855
GROUP_MEMBERS_ID,
5956
FieldValue.arrayUnion(uid)
6057
).addOnSuccessListener {
61-
continuation.resume(true)
58+
cancellableContinuation.resume(true)
6259
}.addOnFailureListener {
63-
continuation.resume(false)
60+
cancellableContinuation.resume(false)
6461
}
6562
}
6663
}
6764

68-
// TODO: suspendcancellablecoroutine๋กœ ๋ณ€๊ฒฝ
6965
suspend fun exitGroup(uid: String, groupId: String): Boolean {
70-
return suspendCoroutine { continuation ->
66+
return suspendCancellableCoroutine { cancellableContinuation ->
7167
db.collection(GROUPS_COLLECTION)
7268
.document(groupId)
7369
.update(
@@ -83,18 +79,17 @@ class GroupDataSource @Inject constructor(
8379
)
8480
)
8581
.addOnSuccessListener {
86-
continuation.resume(true)
82+
cancellableContinuation.resume(true)
8783
}
8884
.addOnFailureListener {
89-
continuation.resume(false)
85+
cancellableContinuation.resume(false)
9086
}
9187
}.addOnFailureListener {
92-
continuation.resume(false)
88+
cancellableContinuation.resume(false)
9389
}
9490
}
9591
}
9692

97-
// TODO Rule ์ถ”๊ฐ€
9893
suspend fun createGroup(
9994
groupName: String,
10095
introduce: String,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.whyranoid.domain.model
2+
3+
sealed class MoGakRunException : Exception() {
4+
5+
object NetworkFailureException : MoGakRunException()
6+
7+
object FileNotFoundedException : MoGakRunException()
8+
9+
object OtherException : MoGakRunException()
10+
}

โ€Žpresentation/src/main/java/com/whyranoid/presentation/community/CommunityItemFragment.kt

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,19 @@ import android.os.Bundle
55
import android.view.View
66
import androidx.core.view.isVisible
77
import androidx.fragment.app.viewModels
8-
import androidx.lifecycle.lifecycleScope
98
import androidx.navigation.fragment.findNavController
109
import com.whyranoid.presentation.R
1110
import com.whyranoid.presentation.base.BaseFragment
1211
import com.whyranoid.presentation.databinding.FragmentCommunityItemBinding
13-
import com.whyranoid.presentation.model.toGroupInfoUiModel
1412
import com.whyranoid.presentation.util.repeatWhenUiStarted
1513
import dagger.hilt.android.AndroidEntryPoint
16-
import kotlinx.coroutines.launch
1714

1815
@AndroidEntryPoint
1916
internal class CommunityItemFragment :
2017
BaseFragment<FragmentCommunityItemBinding>(R.layout.fragment_community_item) {
2118

2219
private val viewModel: CommunityViewModel by viewModels()
2320

24-
init {
25-
observe()
26-
}
27-
2821
private val category by lazy {
2922
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
3023
arguments?.getSerializable(COMMUNITY_CATEGORY_KEY, CommunityCategory::class.java)
@@ -38,6 +31,11 @@ internal class CommunityItemFragment :
3831
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
3932
super.onViewCreated(view, savedInstanceState)
4033

34+
initViews()
35+
observeState()
36+
}
37+
38+
private fun initViews() {
4139
// TODO : ์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„ ๋‹ค๋ฅธ Shimmer Layout ์ƒ์„ฑ
4240
when (category) {
4341
CommunityCategory.BOARD -> {
@@ -52,8 +50,8 @@ internal class CommunityItemFragment :
5250
}
5351
}
5452

55-
private fun observe() {
56-
repeatWhenUiStarted {
53+
private fun observeState() {
54+
viewLifecycleOwner.repeatWhenUiStarted {
5755
viewModel.eventFlow.collect { event ->
5856
handleEvent(event)
5957
}
@@ -64,33 +62,31 @@ internal class CommunityItemFragment :
6462
when (event) {
6563
is Event.CategoryItemClick -> {
6664
val action =
67-
CommunityFragmentDirections.actionCommunityFragmentToGroupDetailFragment(event.groupInfo.toGroupInfoUiModel())
65+
CommunityFragmentDirections.actionCommunityFragmentToGroupDetailFragment(event.groupInfo)
6866
findNavController().navigate(action)
6967
}
7068
}
7169
}
7270

7371
// TODO ์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„ ๋‹ค๋ฅธ ์•„์ดํ…œ ์ฒ˜๋ฆฌ
7472
private fun setMyGroupAdapter() {
75-
val adapter = MyGroupAdapter { groupInfo ->
73+
val myGroupAdapter = MyGroupAdapter { groupInfo ->
7674
viewModel.onCategoryItemClicked(groupInfo)
7775
}
78-
binding.rvCommunity.adapter = adapter
76+
binding.rvCommunity.adapter = myGroupAdapter
7977

80-
viewLifecycleOwner.lifecycleScope.launch {
81-
viewModel.getMyGroupListUseCase().collect { groupList ->
78+
viewLifecycleOwner.repeatWhenUiStarted {
79+
viewModel.myGroupList.collect { groupList ->
8280
removeShimmer()
83-
adapter.submitList(groupList.sortedBy { it.name })
81+
myGroupAdapter.submitList(groupList.sortedBy { it.name })
8482
}
8583
}
8684
}
8785

8886
private fun removeShimmer() {
8987
binding.shimmerCommunity.apply {
90-
if (isShimmerStarted) {
91-
stopShimmer()
92-
isVisible = false
93-
}
88+
stopShimmer()
89+
isVisible = false
9490
}
9591
}
9692

โ€Žpresentation/src/main/java/com/whyranoid/presentation/community/CommunityViewModel.kt

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,49 @@ package com.whyranoid.presentation.community
22

33
import androidx.lifecycle.ViewModel
44
import androidx.lifecycle.viewModelScope
5-
import com.whyranoid.domain.model.GroupInfo
65
import com.whyranoid.domain.usecase.GetMyGroupListUseCase
6+
import com.whyranoid.presentation.model.GroupInfoUiModel
7+
import com.whyranoid.presentation.model.toGroupInfoUiModel
78
import dagger.hilt.android.lifecycle.HiltViewModel
89
import kotlinx.coroutines.flow.MutableSharedFlow
10+
import kotlinx.coroutines.flow.MutableStateFlow
911
import kotlinx.coroutines.flow.SharedFlow
12+
import kotlinx.coroutines.flow.StateFlow
1013
import kotlinx.coroutines.flow.asSharedFlow
14+
import kotlinx.coroutines.flow.asStateFlow
15+
import kotlinx.coroutines.flow.launchIn
16+
import kotlinx.coroutines.flow.onEach
1117
import kotlinx.coroutines.launch
1218
import javax.inject.Inject
1319

1420
@HiltViewModel
1521
class CommunityViewModel @Inject constructor(
16-
val getMyGroupListUseCase: GetMyGroupListUseCase
22+
getMyGroupListUseCase: GetMyGroupListUseCase
1723
) : ViewModel() {
1824

25+
private val _myGroupList = MutableStateFlow<List<GroupInfoUiModel>>(emptyList())
26+
val myGroupList: StateFlow<List<GroupInfoUiModel>>
27+
get() = _myGroupList.asStateFlow()
28+
1929
private val _eventFlow = MutableSharedFlow<Event>()
2030
val eventFlow: SharedFlow<Event>
2131
get() = _eventFlow.asSharedFlow()
2232

23-
fun onCategoryItemClicked(groupInfo: GroupInfo) {
24-
event(Event.CategoryItemClick(groupInfo))
33+
fun onCategoryItemClicked(groupInfo: GroupInfoUiModel) {
34+
emitEvent(Event.CategoryItemClick(groupInfo))
2535
}
2636

27-
private fun event(event: Event) {
37+
private fun emitEvent(event: Event) {
2838
viewModelScope.launch {
2939
_eventFlow.emit(event)
3040
}
3141
}
42+
43+
init {
44+
getMyGroupListUseCase().onEach { groupInfoList ->
45+
_myGroupList.value = groupInfoList.map { groupInfo ->
46+
groupInfo.toGroupInfoUiModel()
47+
}
48+
}.launchIn(viewModelScope)
49+
}
3250
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.whyranoid.presentation.community
22

3-
import com.whyranoid.domain.model.GroupInfo
3+
import com.whyranoid.presentation.model.GroupInfoUiModel
44

55
sealed class Event {
6-
data class CategoryItemClick(val groupInfo: GroupInfo) : Event()
6+
data class CategoryItemClick(val groupInfo: GroupInfoUiModel) : Event()
77
}

โ€Žpresentation/src/main/java/com/whyranoid/presentation/community/MyGroupAdapter.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,31 @@ import android.view.ViewGroup
55
import androidx.recyclerview.widget.DiffUtil
66
import androidx.recyclerview.widget.ListAdapter
77
import androidx.recyclerview.widget.RecyclerView
8-
import com.whyranoid.domain.model.GroupInfo
98
import com.whyranoid.presentation.databinding.MyGroupItemBinding
9+
import com.whyranoid.presentation.model.GroupInfoUiModel
1010

11-
class MyGroupAdapter(private val onClickListener: (GroupInfo) -> Unit) :
12-
ListAdapter<GroupInfo, MyGroupAdapter.MyGroupViewHolder>(diffUtil) {
11+
class MyGroupAdapter(private val onClickListener: (GroupInfoUiModel) -> Unit) :
12+
ListAdapter<GroupInfoUiModel, MyGroupAdapter.MyGroupViewHolder>(diffUtil) {
1313

1414
companion object {
15-
val diffUtil = object : DiffUtil.ItemCallback<GroupInfo>() {
16-
override fun areItemsTheSame(oldItem: GroupInfo, newItem: GroupInfo): Boolean =
15+
val diffUtil = object : DiffUtil.ItemCallback<GroupInfoUiModel>() {
16+
override fun areItemsTheSame(
17+
oldItem: GroupInfoUiModel,
18+
newItem: GroupInfoUiModel
19+
): Boolean =
1720
oldItem.groupId == newItem.groupId
1821

19-
override fun areContentsTheSame(oldItem: GroupInfo, newItem: GroupInfo): Boolean =
22+
override fun areContentsTheSame(
23+
oldItem: GroupInfoUiModel,
24+
newItem: GroupInfoUiModel
25+
): Boolean =
2026
oldItem == newItem
2127
}
2228
}
2329

2430
class MyGroupViewHolder(private val binding: MyGroupItemBinding) :
2531
RecyclerView.ViewHolder(binding.root) {
26-
fun bind(groupInfo: GroupInfo) {
32+
fun bind(groupInfo: GroupInfoUiModel) {
2733
binding.groupInfo = groupInfo
2834
}
2935
}

โ€Žpresentation/src/main/java/com/whyranoid/presentation/community/group/CreateGroupFragment.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ internal class CreateGroupFragment :
2929

3030
setupMenu()
3131

32-
repeatWhenUiStarted {
32+
viewLifecycleOwner.repeatWhenUiStarted {
3333
viewModel.eventFlow.collect { event ->
3434
handleEvent(event)
3535
}
3636
}
3737

38-
repeatWhenUiStarted {
38+
viewLifecycleOwner.repeatWhenUiStarted {
3939
viewModel.rules.collect {
4040
println("ํ…Œ์ŠคํŠธ $it")
4141
}
@@ -105,7 +105,7 @@ internal class CreateGroupFragment :
105105
}
106106
}
107107

108-
repeatWhenUiStarted {
108+
viewLifecycleOwner.repeatWhenUiStarted {
109109
viewModel.isButtonEnable.collect { isEnable ->
110110
if (isEnable) {
111111
binding.topAppBar.menu.setGroupVisible(R.id.ready_to_create, true)

โ€Žpresentation/src/main/java/com/whyranoid/presentation/community/group/detail/GroupDetailFragment.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ internal class GroupDetailFragment :
6666
}
6767

6868
private fun handleEvent() {
69-
repeatWhenUiStarted {
69+
viewLifecycleOwner.repeatWhenUiStarted {
7070
viewModel.eventFlow.collect { event ->
7171
when (event) {
7272
// TODO : ํ™๋ณด ๊ธ€ ์“ฐ๋Ÿฌ๊ฐ€๊ธฐ
@@ -105,7 +105,7 @@ internal class GroupDetailFragment :
105105
val notificationAdapter = GroupNotificationAdapter("hsjeon")
106106

107107
binding.notificationRecyclerView.adapter = notificationAdapter
108-
repeatWhenUiStarted {
108+
viewLifecycleOwner.repeatWhenUiStarted {
109109
viewModel.mergedNotifications.collect { notifications ->
110110
notificationAdapter.submitList(notifications)
111111
}

0 commit comments

Comments
ย (0)