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

[Week7] XML 필수 과제 #19

Open
wants to merge 3 commits into
base: develop-xml
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 5 additions & 4 deletions app/src/main/java/com/sopt/now/data/module/ApiFactory.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.create

object ApiFactory {
private const val BASE_URL: String = BuildConfig.AUTH_BASE_URL
Expand All @@ -31,11 +32,11 @@ object ApiFactory {
.build()
}

inline fun <reified T> createBase(): T = baseRetrofit.create(T::class.java)
inline fun <reified T> createFollower(): T = followerRetrofit.create(T::class.java)
inline fun <reified T> createBaseRetrofit(): T = baseRetrofit.create()
inline fun <reified T> createFollowerRetrofit(): T = followerRetrofit.create()
}

object ServicePool {
val authService = ApiFactory.createBase<AuthService>()
val followerService = ApiFactory.createFollower<FollowerService>()
val authService = ApiFactory.createBaseRetrofit<AuthService>()
val followerService = ApiFactory.createFollowerRetrofit<FollowerService>()
}
17 changes: 17 additions & 0 deletions app/src/main/java/com/sopt/now/repository/FollowerRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.sopt.now.repository

import com.sopt.now.data.model.UserDataResponse
import com.sopt.now.data.module.ServicePool
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import retrofit2.Response

class FollowerRepository {
private val followerService = ServicePool.followerService
Copy link
Member

Choose a reason for hiding this comment

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

follower 라는 네이밍을 한 이유가 있나요?


suspend fun getUserList(page: Int): Response<UserDataResponse> {
return withContext(Dispatchers.IO) {
Copy link
Member

Choose a reason for hiding this comment

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

Dispatchers.IO를 추가하신 이유가 무엇인가요?

Copy link
Member Author

Choose a reason for hiding this comment

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

코루틴을 사용할 때 서버에서 파일 다운로드시 IO를 주입해야한다고 알고있숩니다.!

followerService.getUserList(page).execute()
}
}
}
7 changes: 3 additions & 4 deletions app/src/main/java/com/sopt/now/ui/home/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ class HomeFragment : Fragment() {
setCollect()
}

override fun onDestroy() {
override fun onDestroyView() {
_binding = null
super.onDestroy()
super.onDestroyView()
}

private fun setCollect() {
Expand All @@ -56,8 +56,7 @@ class HomeFragment : Fragment() {

private fun setAdapter() {
val friendAdapter = ItemAdapter(viewModel.friendList)

binding.rvFriends.layoutManager = LinearLayoutManager(requireContext())
binding.rvFriends.adapter = friendAdapter
}
}
}
56 changes: 35 additions & 21 deletions app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
package com.sopt.now.ui.home.viewModel

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sopt.now.R
import com.sopt.now.data.model.ItemData
import com.sopt.now.data.model.UserData
import com.sopt.now.data.model.UserDataResponse
import com.sopt.now.data.module.ServicePool
import com.sopt.now.repository.FollowerRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import kotlinx.coroutines.launch
import java.io.IOException

class HomeViewModel : ViewModel() {
private val followerService by lazy { ServicePool.followerService }
private val followerRepository = FollowerRepository()

private val _followerState = MutableStateFlow<List<UserData>>(emptyList())
val followerState = _followerState.asStateFlow()
private var _eventNetworkError = MutableLiveData(false)
val eventNetworkError: LiveData<Boolean>
get() = _eventNetworkError

Choose a reason for hiding this comment

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

[3]

private var _eventNetworkError = MutableLiveData(false)
val eventNetworkError: LiveData<Boolean> = _eventNetworkError

위와 같이 get()을 제외하고 작성해도 정상 작동합니다. 이유에 대해 알아보시면 좋을 것 같습니다!

Choose a reason for hiding this comment

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

[2]
이벤트를 LiveData 형태로 들고 있으며 다른 observer들이 관찰하게 되면 어떤 문제가 발생할 수 있을까요?
이벤트는 한 번 발생하고 처리되면 사라져야하는 것이 아닐까요?
상태이벤트에 대해 생각해보면 좋을 것 같습니다.

Copy link
Member Author

Choose a reason for hiding this comment

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

LiveData가 MutableLiveData를 감싸서 MutableLiveData의 변화를 관찰할 수 있기 때문에 get을 지워도 되는 것 맞을까요..!??!

Comment on lines 19 to +23

Choose a reason for hiding this comment

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

[5]
StateFlowLiveData를 섞어서 사용하신 이유가 있을까요?

Copy link
Member Author

Choose a reason for hiding this comment

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

StateFlow로 통일하려다가 추가적으로 고치지 못하였습니다..! ㅜㅜ

private var _isNetworkErrorShown = MutableLiveData(false)

Choose a reason for hiding this comment

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

[2]
MutableLiveData를 var로 선언한 이유는 무엇일까요? _isNetworkErrorShown 자체가 바뀌진 않고 LiveData가 감싸고 있는 값만 변경하고 있는 것 같아서 여쭤봅니다!

또 backing property 형태를 사용하지 않고 있는데 앞에 언더바를 붙인 이유도 궁금합니다!

Copy link
Member Author

Choose a reason for hiding this comment

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

_isNetworkErrorShown 자체가 변경되지 않아서 val로 선언하는 것이 적절해보이네욥..!
언더바를 붙인 이유는 외부에서의 접근을 막기 위해 습관적으로 들인 것입니당 ,,!


val friendList = mutableListOf<ItemData>(
ItemData.MyProfile(
Expand All @@ -32,28 +36,38 @@ class HomeViewModel : ViewModel() {
}

private fun fetchFollowerList() {
followerService.getUserList(page = 0).enqueue(object : Callback<UserDataResponse> {
override fun onResponse(
call: Call<UserDataResponse>,
response: Response<UserDataResponse>,
) {
viewModelScope.launch {
try {
val response = followerRepository.getUserList(0)
if (response.isSuccessful) {
val data = response.body()?.data
if (data != null) {
response.body()?.data?.let { data ->
_followerState.value = data
mapFollowersToFriendList(data)
Log.d("FOLLOWER", "$data")
}
_eventNetworkError.value = false
_isNetworkErrorShown.value = false
} else {
_eventNetworkError.value = true
}
} catch (networkError: IOException) {
_eventNetworkError.value = true
}
}
}

override fun onFailure(call: Call<UserDataResponse>, t: Throwable) {
Log.e("HomeError", "${t.message}")
}
})
fun onNetworkErrorShown() {
_isNetworkErrorShown.value = true
}

fun mapFollowersToFriendList(followers: List<UserData>) {
private fun mapFollowersToFriendList(followers: List<UserData>) {
friendList.clear()
friendList.add(
ItemData.MyProfile(
profileImage = R.drawable.img_arin,
name = "김아린",
description = "업보 청산 중..",
),
)
friendList.addAll(followers.map { follower ->
ItemData.Friend(
profileImage = follower.avatar,
Expand All @@ -62,4 +76,4 @@ class HomeViewModel : ViewModel() {
)
})
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.sopt.now.ui.myPage.viewModel

import android.util.Log
import androidx.lifecycle.ViewModel
import com.sopt.now.data.model.ResponseInfoDto
import com.sopt.now.data.model.UserInfo
Expand Down Expand Up @@ -46,7 +45,6 @@ class MyPageViewModel : ViewModel() {
}

override fun onFailure(call: Call<ResponseInfoDto>, t: Throwable) {
Log.e("MyPageError", "${t.message}")
}
})
}
Expand Down