Skip to content
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

Merged
merged 19 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
5bb22dc
[feat] #186 HomeFragment 생성
jihyunniiii Feb 16, 2024
4f12e32
[chore] #186 바텀 네비에 HomeFragment 연결
jihyunniiii Feb 16, 2024
0df7a93
[chore] #186 fragmentStateAdapter Util로 이동
jihyunniiii Feb 16, 2024
afd1511
[feat] #186 HomeFragment UI 구현
jihyunniiii Feb 16, 2024
345f9c0
[chore] #186 지도 및 리스트뷰 UI 수정 (HomeFragment와 공통된 부분 제거)
jihyunniiii Feb 16, 2024
6b4e4b7
[feat] #186 HomeFragment 뷰 전환 로직 구현
jihyunniiii Feb 16, 2024
815f898
[chore] #186 MainListFragment clickListener 제거
jihyunniiii Feb 16, 2024
6d12b27
[chore] #186 네이밍 수정 및 fab visibility 조절
jihyunniiii Feb 16, 2024
b4b71db
[chore] #186 현위치 버튼 MapFragment 이동
jihyunniiii Feb 16, 2024
2640a1a
[feat] #186 Map, Home 로직 분리
jihyunniiii Feb 16, 2024
c12b571
[chore] #186 ktlintFormat
jihyunniiii Feb 16, 2024
845e8d0
Merge branch 'develop' into refactor-list-map
jihyunniiii Feb 16, 2024
80cfc2f
[chore] #186 @+id -> @id
jihyunniiii Feb 17, 2024
8297f48
[feat] #186 프래그먼트 재생성 시 선택된 칩 유지
jihyunniiii Feb 17, 2024
c1b93e8
[feat] #186 HomeFragment 상단에 접속 중인 단체명 뜨도록 구현
jihyunniiii Feb 17, 2024
df84411
[chore] #186 불필요한 scope 함수 제거
jihyunniiii Feb 20, 2024
1ecaa4d
[chore] #186 불필요한 제약 제거
jihyunniiii Feb 20, 2024
4862e92
[chore] #186 vpHome 전환 시 지정된 인덱스가 아닐 경우 아무런 변화 없도록 수정
jihyunniiii Feb 21, 2024
fba57ec
Merge branch 'develop' into refactor-list-map
jihyunniiii Feb 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.fragment.app.replace
import dagger.hilt.android.AndroidEntryPoint
import org.sopt.pingle.R
import org.sopt.pingle.databinding.ActivityMainBinding
import org.sopt.pingle.presentation.ui.main.home.HomeFragment
import org.sopt.pingle.presentation.ui.main.home.map.MapFragment
import org.sopt.pingle.presentation.ui.main.more.MoreFragment
import org.sopt.pingle.presentation.ui.main.mypingle.MyPingleFragment
Expand Down Expand Up @@ -43,7 +44,7 @@ class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main
private fun initBnvMainAllNaviItemSelectedListener() {
binding.bnvMainAllNavi.setOnItemSelectedListener { menuItem ->
when (menuItem.itemId) {
R.id.menu_all_navi_home -> navigateToFragment<MapFragment>()
R.id.menu_all_navi_home -> navigateToFragment<HomeFragment>()
R.id.menu_all_navi_ranking -> navigateToFragment<RankingFragment>()
R.id.menu_all_navi_plan -> navigateToPlanAnnouncement()
R.id.menu_all_navi_mypingle -> navigateToFragment<MyPingleFragment>()
Expand Down
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 }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기는 꼭 findViewById를 사용해야만 하나욤? 궁금핑..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cgHomeCategory 그룹에서 id가 checkedIds인 값을 받아와야 하기 때문에 findViewById 사용하였숩니다.
찾아보니까 칩그룹에서 선택된 값을 가져오려면 무조건 저렇게 해야하는 것 같더라구요?
다른 방법을 아직 못 찾았어요 ㅜ

)
}

fabHomeChange.setOnClickListener {
vpHome.setCurrentItem(
when (vpHome.currentItem) {
MAP_INDEX -> MAIN_LIST_INDEX
else -> MAP_INDEX
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개취이긴 하지만! 전 뭔가 else보다 명확하게 명시해주는게 더 가독성 측면에서 좋은거 같기두 하네여 ~~

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else를 무조건 넣으라 해서,,, else로 했습니다요 ㅠㅠ

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아항 그럼 else문을 따로 둘 수도 이ㅛ지 않을까염

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그러명

MAP_INDEX -> MAIN_LIST_INDEX
MAIN_LIST_INDEX -> MAP_INDEX
else -> MAP_INDEX

이런 식으로 되어야 할 것 같은데 이게 더 나을까욤? 두 개의 반환 값이 같아서 하나로 쓰는 게 더 낫지 않을까 생각했거든요

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아 MAP_INDEX가 아닌 경우도 고려해서 else문에 MAP_INDEX로 가는건가여,,?? 이거 뷰페이저 index 두 개 아닌가염?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이게 fragmentStateAdapter에 리스트를 2개 넣어주긴 하는데 vpHome.currentItem 값이 무조건 2개는 아니라 그런 듯요???? 몇 개 넣어주냐에 따라 다르니까,,?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[다은] 지정된 인덱스가 아닐 때는 아무 일도 안 일어나도록 고쳐줘욤 ~

},
false
)
}
}
}

private fun collectData() {
homeViewModel.category.flowWithLifecycle(viewLifecycleOwner.lifecycle)
.distinctUntilChanged()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우리 그때 피드백 받을 때 stateflow에는 사실상 distinctUntilChanged()가 포함되어 있으니까 써줄 필요가 없다고 했자나요.. 이걸 빼면 제대로 작동이 안되나요 여기도?!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넹 여긴 없으면 안 되네요 ㅜㅜ
distinctUntilChanged 이거 관련 리팩은 로직 다 짜구 하려구욤 ㅠㅠ

Copy link
Collaborator

Choose a reason for hiding this comment

The 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
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

binding이라는 변수가 한번 사용되는거 같은데 스코프함수를 사용해야하는 건가요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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
Expand All @@ -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,
Expand Down Expand Up @@ -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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

별거 아닌 질문이긴 한데욥ㅋ.ㅋ 이 코드를 굳이 상단으로 올린 이유는 먼가요?
근데 진짜 궁금핑....

Copy link
Collaborator Author

Choose a reason for hiding this comment

The 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()
Expand Down Expand Up @@ -105,6 +105,8 @@ class MapViewModel @Inject constructor(
}
}

fun getGroupName(): String = localStorage.groupName

fun getPinListWithoutFilter() {
viewModelScope.launch {
_pinEntityListState.value = UiState.Loading
Expand Down
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

얘가 이제 머지 후에 작업해야 하는 파일인가부네용

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞슴다,,

Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,10 @@ import android.os.Bundle
import android.view.View
import org.sopt.pingle.R
import org.sopt.pingle.databinding.FragmentMainListBinding
import org.sopt.pingle.presentation.ui.main.home.map.MapFragment
import org.sopt.pingle.util.base.BindingFragment
import org.sopt.pingle.util.fragment.navigateToFragment

class MainListFragment : BindingFragment<FragmentMainListBinding>(R.layout.fragment_main_list) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

addListeners()
}

private fun addListeners() {
binding.fabMainListMap.setOnClickListener {
navigateToFragment<MapFragment>()
}
}
}
Loading
Loading