Skip to content

Commit

Permalink
[feat/upgrade_search]: 그룹 가져오는 API 연결
Browse files Browse the repository at this point in the history
  • Loading branch information
soopeach committed Mar 18, 2024
1 parent a71ffe0 commit 3a17126
Show file tree
Hide file tree
Showing 14 changed files with 167 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.gdsc.data.database

import androidx.paging.PagingSource
import androidx.paging.PagingState
import org.gdsc.data.network.GroupAPI
import org.gdsc.domain.model.GroupPreview
import org.gdsc.domain.model.request.GroupSearchRequest

class GroupBySearchPagingSource(
private val api: GroupAPI,
private val groupSearchRequest: GroupSearchRequest,
): PagingSource<Int, GroupPreview>() {
override fun getRefreshKey(state: PagingState<Int, GroupPreview>): Int? {
return state.anchorPosition?.let { anchorPosition ->
val anchorPage = state.closestPageToPosition(anchorPosition)
anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
}
}

override suspend fun load(params: LoadParams<Int>): LoadResult<Int, GroupPreview> {
val page = params.key ?: 1
return try {
val items = api.searchGroup(groupSearchRequest)
LoadResult.Page(
data = items.data.groupList,
prevKey = null,
nextKey = if (items.data.groupList.isEmpty()) null else page + 1
)
} catch (e: Exception) {
return LoadResult.Error(e)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.gdsc.data.datasource

import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow
import org.gdsc.domain.model.GroupPreview
import org.gdsc.domain.model.response.Group

Expand All @@ -10,4 +12,6 @@ interface GroupDataSource {
suspend fun selectGroup(groupId: Int): String

suspend fun searchGroup(keyword: String, limitCount: Int): List<GroupPreview>

suspend fun searchPagingGroup(keyword: String): Flow<PagingData<GroupPreview>>
}
28 changes: 25 additions & 3 deletions data/src/main/java/org/gdsc/data/datasource/GroupDataSourceImpl.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package org.gdsc.data.datasource

import android.util.Log
import org.gdsc.data.database.GroupPaging
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import org.gdsc.data.database.GroupBySearchPagingSource
import org.gdsc.data.network.GroupAPI
import org.gdsc.domain.model.GroupPreview
import org.gdsc.domain.model.request.GroupSearchRequest
Expand All @@ -10,7 +16,7 @@ import javax.inject.Inject

class GroupDataSourceImpl @Inject constructor(
private val groupAPI: GroupAPI,
): GroupDataSource {
) : GroupDataSource {
override suspend fun getMyGroups(): List<Group> {
runCatching {
groupAPI.getMyGroups()
Expand All @@ -36,4 +42,20 @@ class GroupDataSourceImpl @Inject constructor(
override suspend fun searchGroup(keyword: String, limitCount: Int): List<GroupPreview> {
return groupAPI.searchGroup(GroupSearchRequest(keyword)).data.groupList.take(limitCount)
}

override suspend fun searchPagingGroup(
keyword: String,
): Flow<PagingData<GroupPreview>> {
return Pager(
config = PagingConfig(
pageSize = 20,
enablePlaceholders = true
)
) {
GroupBySearchPagingSource(
groupAPI,
GroupSearchRequest(keyword))
}.flow.cachedIn(CoroutineScope(Dispatchers.IO))

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.gdsc.data.repository

import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow
import org.gdsc.data.datasource.GroupDataSource
import org.gdsc.domain.model.GroupPreview
import org.gdsc.domain.model.response.Group
Expand All @@ -20,4 +22,8 @@ class GroupRepositoryImpl @Inject constructor(
override suspend fun searchGroup(keyword: String, limitCount: Int): List<GroupPreview> {
return groupDataSource.searchGroup(keyword, limitCount)
}

override suspend fun searchPagingGroup(keyword: String): Flow<PagingData<GroupPreview>> {
return groupDataSource.searchPagingGroup(keyword)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.gdsc.domain.repository

import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow
import org.gdsc.domain.model.GroupPreview
import org.gdsc.domain.model.response.Group

Expand All @@ -9,4 +11,6 @@ interface GroupRepository {
suspend fun selectGroup(groupId: Int): String

suspend fun searchGroup(keyword: String, limitCount: Int): List<GroupPreview>

suspend fun searchPagingGroup(keyword: String): Flow<PagingData<GroupPreview>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.gdsc.domain.usecase

import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow
import org.gdsc.domain.model.GroupPreview
import org.gdsc.domain.repository.GroupRepository
import javax.inject.Inject

class GetGroupBySearchUseCase @Inject constructor(
private val groupRepository: GroupRepository
) {
suspend operator fun invoke(
keyword: String,
): Flow<PagingData<GroupPreview>> {

return groupRepository.searchPagingGroup(keyword)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.gdsc.domain.SortType
import org.gdsc.domain.model.GroupPreview
import org.gdsc.domain.model.Location
import org.gdsc.domain.model.RegisteredRestaurant
import org.gdsc.domain.usecase.GetGroupBySearchUseCase
import org.gdsc.domain.usecase.GetGroupBySearchWithLimitCountUseCase
import org.gdsc.domain.usecase.GetRestaurantBySearchUseCase
import org.gdsc.domain.usecase.GetRestaurantBySearchWithLimitCountUseCase
Expand All @@ -35,7 +36,8 @@ class AllSearchViewModel @Inject constructor(
private val deleteSearchedKeywordUseCase: DeleteSearchedKeywordUseCase,
private val initSearchedKeywordUseCase: InitSearchedKeywordUseCase,
private val getRestaurantBySearchWithLimitCountUseCase: GetRestaurantBySearchWithLimitCountUseCase,
private val getGroupBySearchWithLimitCountUseCase: GetGroupBySearchWithLimitCountUseCase
private val getGroupBySearchWithLimitCountUseCase: GetGroupBySearchWithLimitCountUseCase,
private val getGroupBySearchUseCase: GetGroupBySearchUseCase
) : ViewModel() {

init {
Expand Down Expand Up @@ -81,6 +83,12 @@ class AllSearchViewModel @Inject constructor(
private var _searchedGroupPreviewState =
MutableStateFlow<List<GroupPreview>>(emptyList())

val searchedGroupState: StateFlow<PagingData<GroupPreview>>
get() = _searchedGroupState

private var _searchedGroupState =
MutableStateFlow<PagingData<GroupPreview>>(PagingData.empty())

val searchedGroupPreviewState: StateFlow<List<GroupPreview>>
get() = _searchedGroupPreviewState

Expand Down Expand Up @@ -166,6 +174,12 @@ class AllSearchViewModel @Inject constructor(
val result = getGroupBySearchWithLimitCountUseCase(searchKeyword.value, 3)
_searchedGroupPreviewState.value = result
}
viewModelScope.launch {
getGroupBySearchUseCase(searchKeyword.value).distinctUntilChanged()
.collect {
_searchedGroupState.value = it
}
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ class SearchCategoryAllFragment(
viewModel.isForGroup.collect { isForGroup ->
if (isForGroup.not()) {
binding.restaurantRecyclerView.visibility = View.GONE
binding.waringNoRestaurant.root.visibility = View.VISIBLE
binding.warningNoRestaurant.root.visibility = View.VISIBLE
} else {
binding.restaurantRecyclerView.visibility = View.VISIBLE
binding.waringNoRestaurant.root.visibility = View.GONE
binding.warningNoRestaurant.root.visibility = View.GONE
}
}
}
Expand All @@ -60,10 +60,10 @@ class SearchCategoryAllFragment(
viewModel.searchedGroupPreviewState.collect {
if (it.isEmpty()) {
binding.groupRecyclerView.visibility = View.GONE
binding.waringNoGroup.root.visibility = View.VISIBLE
binding.warningNoGroup.root.visibility = View.VISIBLE
} else {
binding.groupRecyclerView.visibility = View.VISIBLE
binding.waringNoGroup.root.visibility = View.GONE
binding.warningNoGroup.root.visibility = View.GONE

}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.recyclerview.widget.LinearLayoutManager
import org.gdsc.presentation.databinding.FragmentSearchCategoryGroupBinding
import org.gdsc.presentation.utils.repeatWhenUiStarted
import org.gdsc.presentation.view.allsearch.adapter.SearchCategoryGroupAdapter
import org.gdsc.presentation.view.allsearch.adapter.SearchCategoryGroupPreviewAdapter

class SearchCategoryGroupFragment(
private val searchKeyword: String
Expand All @@ -27,5 +31,28 @@ class SearchCategoryGroupFragment(

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

repeatWhenUiStarted {
viewModel.searchedGroupPreviewState.collect {
if (it.isEmpty()) {
binding.groupRecyclerView.visibility = View.GONE
binding.warningNoGroup.root.visibility = View.VISIBLE
} else {
binding.groupRecyclerView.visibility = View.VISIBLE
binding.warningNoGroup.root.visibility = View.GONE

}
}
}

val adapter = SearchCategoryGroupAdapter()
binding.groupRecyclerView.adapter = adapter
binding.groupRecyclerView.layoutManager = LinearLayoutManager(requireContext())

repeatWhenUiStarted {
viewModel.searchedGroupState.collect {
adapter.submitData(it)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ class SearchCategoryRestaurantFragment(
viewModel.isForGroup.collect{ isForGroup ->
if (isForGroup.not()) {
binding.restaurantRecyclerView.visibility = View.GONE
binding.waringNoRestaurant.root.visibility = View.VISIBLE
binding.warningNoRestaurant.root.visibility = View.VISIBLE
} else {
binding.restaurantRecyclerView.visibility = View.VISIBLE
binding.waringNoRestaurant.root.visibility = View.GONE
binding.warningNoRestaurant.root.visibility = View.GONE
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,32 @@ import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import org.gdsc.domain.model.GroupInfo
import org.gdsc.domain.model.GroupPreview
import org.gdsc.presentation.R
import org.gdsc.presentation.databinding.ItemSearchGroupBinding

class SearchCategoryGroupAdapter() :
PagingDataAdapter<GroupInfo, SearchCategoryGroupAdapter.SearchCategoryGroupViewHolder>(
PagingDataAdapter<GroupPreview, SearchCategoryGroupAdapter.SearchCategoryGroupViewHolder>(
DiffCallback
) {

companion object DiffCallback : DiffUtil.ItemCallback<GroupInfo>() {
override fun areItemsTheSame(oldItem: GroupInfo, newItem: GroupInfo): Boolean {
companion object DiffCallback : DiffUtil.ItemCallback<GroupPreview>() {
override fun areItemsTheSame(oldItem: GroupPreview, newItem: GroupPreview): Boolean {
return oldItem.groupId == newItem.groupId
}

override fun areContentsTheSame(oldItem: GroupInfo, newItem: GroupInfo): Boolean {
override fun areContentsTheSame(oldItem: GroupPreview, newItem: GroupPreview): Boolean {
return oldItem == newItem
}
}

class SearchCategoryGroupViewHolder(
private val binding: ItemSearchGroupBinding,
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: GroupInfo) {
fun bind(item: GroupPreview) {
binding.run {
Glide.with(itemView.context)
.load(item.groupProfileImageUrl)
.load("https://picsum.photos/200")
.placeholder(R.drawable.base_profile_image)
.into(ivGroupImage)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
android:layout_marginHorizontal="@dimen/default_spacing">

<include
android:id="@+id/waring_no_restaurant"
android:id="@+id/warning_no_restaurant"
layout="@layout/restaurant_is_only_for_people_in_group"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Expand Down Expand Up @@ -102,7 +102,7 @@
app:layout_constraintEnd_toEndOf="parent">

<include
android:id="@+id/waring_no_group"
android:id="@+id/warning_no_group"
layout="@layout/there_is_no_group"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="group"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/group_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="40dp"
android:layout_marginHorizontal="@dimen/default_spacing"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
tools:layout_editor_absoluteX="0dp" />

<include
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/warning_no_group"
layout="@layout/there_is_no_group"
android:layout_marginHorizontal="@dimen/default_spacing"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
<include
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/waring_no_restaurant"
android:id="@+id/warning_no_restaurant"
layout="@layout/restaurant_is_only_for_people_in_group"
android:layout_marginBottom="40dp"
android:layout_marginHorizontal="@dimen/default_spacing"
Expand Down

0 comments on commit 3a17126

Please sign in to comment.