-
Notifications
You must be signed in to change notification settings - Fork 0
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] 앱잼 전 세미나 코드 리팩토링 #22
base: develop-compose
Are you sure you want to change the base?
Changes from 7 commits
d689df0
51db35c
2dc3df5
abcc490
e030c2d
aae57df
1638b2c
e55297f
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,11 @@ | ||
package com.sopt.now.compose | ||
|
||
import android.app.Application | ||
import dagger.hilt.android.HiltAndroidApp | ||
|
||
@HiltAndroidApp | ||
class App : Application() { | ||
override fun onCreate() { | ||
super.onCreate() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.sopt.now.compose.repository | ||
|
||
import com.sopt.now.compose.data.model.ResponseUserDto | ||
import com.sopt.now.compose.data.network.FollowerService | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.withContext | ||
import retrofit2.Response | ||
import javax.inject.Inject | ||
import javax.inject.Singleton | ||
|
||
@Singleton | ||
class FollowerRepository @Inject constructor( | ||
private val followerService: FollowerService, | ||
Comment on lines
+12
to
+13
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. 굿굿 좋아요! 다만 아직 클린아키텍처가 적용되어 있지 않은 것 같아서 domain 레이어를 추가했을 때 코드가 어떻게 수정될 지 한번 생각해보면 좋을 것 같아요!! |
||
) { | ||
suspend fun getUserList(page: Int): Response<ResponseUserDto> { | ||
return withContext(Dispatchers.IO) { | ||
followerService.getUserList(page).execute() | ||
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. 서버로 네트워크 요청 보내서 파일 받아올 때, 메인 스레드가 아닌 별도 스레드에서 실행시키고자 작성했습니다! |
||
} | ||
} | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,11 +8,12 @@ import androidx.compose.runtime.collectAsState | |
import androidx.compose.runtime.getValue | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.tooling.preview.Preview | ||
import androidx.lifecycle.viewmodel.compose.viewModel | ||
import androidx.hilt.navigation.compose.hiltViewModel | ||
import com.sopt.now.compose.R | ||
|
||
|
||
@Composable | ||
fun HomeScreen(homeViewModel: HomeViewModel = viewModel()) { | ||
fun HomeScreen(homeViewModel: HomeViewModel = hiltViewModel()) { | ||
val followerState by homeViewModel.followerState.collectAsState() | ||
Comment on lines
+16
to
17
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. flow를 사용한다면 collectAsStateWithLifecycle로 사용해주는 걸 습관화하면 좋을 것 같아요! 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. 헉 꼼꼼하다 넵!!!! |
||
|
||
LazyColumn(modifier = Modifier.fillMaxSize()) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,71 @@ | ||
package com.sopt.now.compose.ui.home | ||
|
||
import android.util.Log | ||
import androidx.lifecycle.LiveData | ||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.ViewModel | ||
import androidx.lifecycle.viewModelScope | ||
import com.sopt.now.compose.data.model.Profile | ||
import com.sopt.now.compose.data.model.ResponseUserDto | ||
import com.sopt.now.compose.data.model.UserDataDto | ||
import com.sopt.now.compose.data.module.ServicePool | ||
import com.sopt.now.compose.repository.FollowerRepository | ||
import dagger.hilt.android.lifecycle.HiltViewModel | ||
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 | ||
import javax.inject.Inject | ||
|
||
class HomeViewModel : ViewModel() { | ||
private val followerService by lazy { ServicePool.followerService } | ||
@HiltViewModel | ||
class HomeViewModel @Inject constructor( | ||
private val followerRepository: FollowerRepository, | ||
) : ViewModel() { | ||
|
||
private val _followerState = MutableStateFlow<List<UserDataDto>>(emptyList()) | ||
val followerState = _followerState.asStateFlow() | ||
|
||
val friendList = mutableListOf<Profile>() | ||
private var _eventNetworkError = MutableLiveData(false) | ||
|
||
private var _isNetworkErrorShown = MutableLiveData(false) | ||
Comment on lines
+23
to
+25
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. 혹시 두 변수들이 어디서 쓰이고 있는 건가용..? 이 뷰모델에서 true 혹은 false로 바꿔주고 그 이후에 사용되는 부분을 못 찾아서요!! 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. fetchFollowerList에서 네트워크 오류 발생시 쓰이는데, 사실 삭제해도 될 것 같아욥!!! |
||
|
||
private val friendList = mutableListOf<Profile>() | ||
|
||
init { | ||
fetchFollowerList() | ||
} | ||
|
||
private fun fetchFollowerList() { | ||
followerService.getUserList(page = 0).enqueue(object : Callback<ResponseUserDto> { | ||
override fun onResponse( | ||
call: Call<ResponseUserDto>, | ||
response: Response<ResponseUserDto>, | ||
) { | ||
viewModelScope.launch { | ||
try { | ||
val response = followerRepository.getUserList(0) | ||
if (response.isSuccessful) { | ||
val data = response.body()?.data | ||
if (data != null) { | ||
response.body()?.data?.let { data -> | ||
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. 제가 생각하기에 response가 success인 경우라면 null이 아닐 것 같은데 nullable로 선언해준 이유가 있나용...? 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. 성공적인 응답일 때에도 간혹 데이터가 없을 수 있어서 (post 요청 등....!) 일단 nullable로 처리했는데, 터닝에서는 굳이 필요 없을 것 같습니당..!!!! |
||
_followerState.value = data | ||
mapFollowersToFriendList(data) | ||
} | ||
_eventNetworkError.value = false | ||
_isNetworkErrorShown.value = false | ||
} else { | ||
_eventNetworkError.value = true | ||
} | ||
} catch (networkError: IOException) { | ||
_eventNetworkError.value = true | ||
Log.e("HomeError", "${networkError.message}") | ||
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. 참고로 터닝에서는 레포지토리 패턴을 사용하기 때문에 RepositoryImpl 파일에서 runCatching을 사용해준다면 뷰모델에서는 따로 사용해줄 필요가 없답니다! 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. 로그는 지워줍시당!! |
||
} | ||
} | ||
} | ||
|
||
override fun onFailure(call: Call<ResponseUserDto>, t: Throwable) { | ||
Log.e("HomeError", "${t.message}") | ||
} | ||
}) | ||
fun onNetworkErrorShown() { | ||
_isNetworkErrorShown.value = true | ||
} | ||
|
||
fun mapFollowersToFriendList(followers: List<UserDataDto>) { | ||
for (follower in followers) { | ||
friendList.add( | ||
Profile( | ||
profileImage = follower.avatar, | ||
name = "${follower.firstName} ${follower.lastName}", | ||
description = follower.email | ||
) | ||
private fun mapFollowersToFriendList(followers: List<UserDataDto>) { | ||
friendList.clear() | ||
friendList.addAll(followers.map { follower -> | ||
Profile( | ||
profileImage = follower.avatar, | ||
name = "${follower.firstName} ${follower.lastName}", | ||
description = follower.email | ||
) | ||
} | ||
}) | ||
} | ||
} | ||
} |
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.
현재 레포지토리 모듈과 서비스 모듈을 같은 파일에 넣어둔 것 같은데,
서로 다른 기능을 하는 모듈이면 다른 파일로 분류하는 게 좋을 것 같아요!
지금은 함수가 하나씩 존재하지만 여러 개의 함수가 있다면 헷갈릴 수 있으니까요!