-
Notifications
You must be signed in to change notification settings - Fork 2
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
[refactor] 리스트뷰 <-> 지도뷰 ViewPager로 리팩토링 #187
Changes from 15 commits
5bb22dc
4f12e32
0df7a93
afd1511
345f9c0
6b4e4b7
815f898
6d12b27
b4b71db
2640a1a
c12b571
845e8d0
80cfc2f
8297f48
c1b93e8
df84411
1ecaa4d
4862e92
fba57ec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
package org.sopt.pingle.presentation.ui.main.home | ||
|
||
import android.os.Bundle | ||
import android.view.View | ||
import androidx.fragment.app.Fragment | ||
import androidx.fragment.app.activityViewModels | ||
import androidx.lifecycle.flowWithLifecycle | ||
import androidx.lifecycle.lifecycleScope | ||
import androidx.viewpager2.widget.ViewPager2 | ||
import dagger.hilt.android.AndroidEntryPoint | ||
import kotlinx.coroutines.flow.distinctUntilChanged | ||
import kotlinx.coroutines.flow.launchIn | ||
import kotlinx.coroutines.flow.onEach | ||
import org.sopt.pingle.R | ||
import org.sopt.pingle.databinding.FragmentHomeBinding | ||
import org.sopt.pingle.presentation.type.CategoryType | ||
import org.sopt.pingle.presentation.ui.main.home.mainlist.MainListFragment | ||
import org.sopt.pingle.presentation.ui.main.home.map.MapFragment | ||
import org.sopt.pingle.util.base.BindingFragment | ||
import org.sopt.pingle.util.component.PingleChip | ||
import org.sopt.pingle.util.view.PingleFragmentStateAdapter | ||
|
||
@AndroidEntryPoint | ||
class HomeFragment : BindingFragment<FragmentHomeBinding>(R.layout.fragment_home) { | ||
private val homeViewModel: HomeViewModel by activityViewModels() | ||
private lateinit var fragmentList: ArrayList<Fragment> | ||
private lateinit var fragmentStateAdapter: PingleFragmentStateAdapter | ||
|
||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||
super.onViewCreated(view, savedInstanceState) | ||
|
||
initLayout() | ||
addListeners() | ||
collectData() | ||
setFragmentStateAdapter() | ||
} | ||
|
||
private fun initLayout() { | ||
with(binding) { | ||
chipHomeCategoryPlay.setChipCategoryType(CategoryType.PLAY) | ||
chipHomeCategoryStudy.setChipCategoryType(CategoryType.STUDY) | ||
chipHomeCategoryMulti.setChipCategoryType(CategoryType.MULTI) | ||
chipHomeCategoryOthers.setChipCategoryType(CategoryType.OTHERS) | ||
|
||
when (homeViewModel.category.value) { | ||
CategoryType.PLAY -> chipHomeCategoryPlay.isChecked = true | ||
CategoryType.STUDY -> chipHomeCategoryStudy.isChecked = true | ||
CategoryType.MULTI -> chipHomeCategoryMulti.isChecked = true | ||
CategoryType.OTHERS -> chipHomeCategoryOthers.isChecked = true | ||
else -> Unit | ||
} | ||
|
||
tvHomeGroup.text = homeViewModel.getGroupName() | ||
} | ||
} | ||
|
||
private fun addListeners() { | ||
with(binding) { | ||
cgHomeCategory.setOnCheckedStateChangeListener { group, checkedIds -> | ||
homeViewModel.setCategory( | ||
category = checkedIds.getOrNull(SINGLE_SELECTION) | ||
?.let { group.findViewById<PingleChip>(it).categoryType } | ||
) | ||
} | ||
|
||
fabHomeChange.setOnClickListener { | ||
vpHome.setCurrentItem( | ||
when (vpHome.currentItem) { | ||
MAP_INDEX -> MAIN_LIST_INDEX | ||
else -> MAP_INDEX | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 개취이긴 하지만! 전 뭔가 else보다 명확하게 명시해주는게 더 가독성 측면에서 좋은거 같기두 하네여 ~~ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. else를 무조건 넣으라 해서,,, else로 했습니다요 ㅠㅠ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아항 그럼 else문을 따로 둘 수도 이ㅛ지 않을까염 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 아 MAP_INDEX가 아닌 경우도 고려해서 else문에 MAP_INDEX로 가는건가여,,?? 이거 뷰페이저 index 두 개 아닌가염? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이게 fragmentStateAdapter에 리스트를 2개 넣어주긴 하는데 vpHome.currentItem 값이 무조건 2개는 아니라 그런 듯요???? 몇 개 넣어주냐에 따라 다르니까,,? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [다은] 지정된 인덱스가 아닐 때는 아무 일도 안 일어나도록 고쳐줘욤 ~ |
||
}, | ||
false | ||
) | ||
} | ||
} | ||
} | ||
|
||
private fun collectData() { | ||
homeViewModel.category.flowWithLifecycle(viewLifecycleOwner.lifecycle) | ||
.distinctUntilChanged() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 우리 그때 피드백 받을 때 stateflow에는 사실상 distinctUntilChanged()가 포함되어 있으니까 써줄 필요가 없다고 했자나요.. 이걸 빼면 제대로 작동이 안되나요 여기도?! There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 어떻게 그럴까,,, stateFlow는 내부적으로 저게 처리가 돼있는데,, 원인을 찾아봐야겠네요 구독 시점의 여부일 수 있어요 |
||
.onEach { | ||
homeViewModel.getPinListWithoutFilter() | ||
}.launchIn(viewLifecycleOwner.lifecycleScope) | ||
|
||
homeViewModel.markerModelData.flowWithLifecycle(viewLifecycleOwner.lifecycle) | ||
.onEach { markerModelData -> | ||
(markerModelData.first == HomeViewModel.DEFAULT_SELECTED_MARKER_POSITION).let { isMarkerUnselected -> | ||
with(binding) { | ||
fabHomeChange.visibility = | ||
if (isMarkerUnselected) View.VISIBLE else View.INVISIBLE | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. binding이라는 변수가 한번 사용되는거 같은데 스코프함수를 사용해야하는 건가요?? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아 이게 원래 2개였는데 하나로 변경돼서 ㅜㅜ 반영할게요 ~ |
||
} | ||
}.launchIn(viewLifecycleOwner.lifecycleScope) | ||
} | ||
|
||
private fun setFragmentStateAdapter() { | ||
fragmentList = ArrayList() | ||
fragmentList.apply { | ||
add(MapFragment()) | ||
add(MainListFragment()) | ||
} | ||
|
||
fragmentStateAdapter = PingleFragmentStateAdapter(fragmentList, requireActivity()) | ||
|
||
with(binding.vpHome) { | ||
adapter = fragmentStateAdapter | ||
isUserInputEnabled = false | ||
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { | ||
override fun onPageSelected(position: Int) { | ||
super.onPageSelected(position) | ||
with(binding) { | ||
(vpHome.currentItem == MAP_INDEX).let { isMap -> | ||
fabHomeChange.setImageResource(if (isMap) R.drawable.ic_map_list_24 else R.drawable.ic_map_map_24) | ||
} | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
|
||
companion object { | ||
private const val SINGLE_SELECTION = 0 | ||
const val MAP_INDEX = 0 | ||
const val MAIN_LIST_INDEX = 1 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package org.sopt.pingle.presentation.ui.main.home.map | ||
package org.sopt.pingle.presentation.ui.main.home | ||
|
||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
|
@@ -22,7 +22,7 @@ import org.sopt.pingle.presentation.type.CategoryType | |
import org.sopt.pingle.util.view.UiState | ||
|
||
@HiltViewModel | ||
class MapViewModel @Inject constructor( | ||
class HomeViewModel @Inject constructor( | ||
private val localStorage: PingleLocalDataSource, | ||
private val getPinListWithoutFilteringUseCase: GetPinListWithoutFilteringUseCase, | ||
private val getPingleListUseCase: GetPingleListUseCase, | ||
|
@@ -55,17 +55,17 @@ class MapViewModel @Inject constructor( | |
private val _pingleDeleteState = MutableSharedFlow<UiState<Unit?>>() | ||
val pingleDeleteState get() = _pingleDeleteState.asSharedFlow() | ||
|
||
fun setCategory(category: CategoryType?) { | ||
_category.value = category | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. 원래 변수 순서에 맞춰서 함수도 배열하는 편인데요,, 얘가 혼자 아래 가있더라구요? 그래서 위로 올렸어용 |
||
} | ||
|
||
private fun setMarkerModelListIsSelected(position: Int) { | ||
_markerModelData.value.second[position].isSelected.set(!_markerModelData.value.second[position].isSelected.get()) | ||
} | ||
|
||
private fun getMarkerModelSelected(position: Int) = | ||
_markerModelData.value.second[position].isSelected.get() | ||
|
||
fun setCategory(category: CategoryType?) { | ||
_category.value = category | ||
} | ||
|
||
fun clearMarkerModelData() { | ||
_markerModelData.value.second.forEach { it.marker.map = null } | ||
_markerModelData.value.second.clear() | ||
|
@@ -105,6 +105,8 @@ class MapViewModel @Inject constructor( | |
} | ||
} | ||
|
||
fun getGroupName(): String = localStorage.groupName | ||
|
||
fun getPinListWithoutFilter() { | ||
viewModelScope.launch { | ||
_pinEntityListState.value = UiState.Loading | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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.
여기는 꼭 findViewById를 사용해야만 하나욤? 궁금핑..
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.
cgHomeCategory 그룹에서 id가 checkedIds인 값을 받아와야 하기 때문에 findViewById 사용하였숩니다.
찾아보니까 칩그룹에서 선택된 값을 가져오려면 무조건 저렇게 해야하는 것 같더라구요?
다른 방법을 아직 못 찾았어요 ㅜ