먼저 mvvm 구조를 따라 view, viewModel로 나누어, UI와 데이터 처리 부분을 구분해주었습니다.
LoginActivity에는 Activity를 구성하는데 필요한 것만 넣어주었습니다.
(sdk 초기화에 필요한 암호들은 --로 처리하여 업로드 합니다.)
@AndroidEntryPoint
class LoginActivity : ComponentActivity() {
@Inject lateinit var viewModel: LoginViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
UsDividendTheme {
// SDK init
KakaoSdk.init(this, "--")
NaverIdLoginSDK.initialize(this, "--", "--", "미주정복")
LoginView(viewModel)
}
}
}
}
LoginView는 @Compose로 화면을 구성하였던 함수만을 넣어주었습니다.
LoginViewModel은 sns 로그인을 실행하고, 서버에 정보를 보내주는 함수를 넣었습니다.
viewModel에서 페이지를 넘기도록 설정하기 위해서 viewModel의 함수에 context를 인자로 넣어주었는데, 찾아보니 이렇게 구현하면 안 되었습니다.
이는 Activity가 onDestroy된 후 ViewModel이 onCleared로 사라지기 때문입니다.
예를 들어 가로 또는 세로로 변경가능한, 화면이 있다고 가정해봅시다.
가로 <-> 세로 모드로 변경할 때는 화면이 onDestroy 이후 onCreate로 다시 이동합니다.
만약 ViewModel에게 context 준다면 화면 방향이 변경된 후의 ViewModel은 이전 화면의 context를 가지고 있게 되는 것입니다.
이를 방지하기 위해서 @ActivityContext를 사용하였다.
ViewModel를 사용하고자 하는 Activity의 context를 사용할 수 있게 해준다.
@HiltViewModel
@AndroidEntryPoint
class LoginViewModel @Inject constructor(
@ActivityContext private val context: Context
) : ViewModel() {
이렇게 하면
This field leaks a context object 와 같은 warning이 뜨는데 아래의 링크를 확인하면 그냥 업데이트를 하면서 생긴 에러로 warning이 뜨는 것 같다.
https://stackoverflow.com/questions/66216839/inject-context-with-hilt-this-field-leaks-a-context-object
mvvm 형태로 또 hilt를 사용하여 구현하기 위해
NetworkModule, LoginRepository 파일을 만들었다.
NetworkModule은 아래의 링크를 참조하여 만들었다.
https://rccode.tistory.com/296
LoginRepository는 apiService의 signUp 함수를 사용할 수 있도록 만들었다.
@AndroidEntryPoint
class LoginRepository @Inject constructor(private val apiService: ApiService) {
@WorkerThread
suspend fun signUp(nameEmailData: NameEmailData) = apiService.signUp(nameEmailData)
}
이를 ViewModel에 적용시키면 아래와 같다.
viewModelScope.launch {
val serverAnswer = loginRepository.signUp(
NameEmailData(nickname!!, email!!)
)
when (serverAnswer.isSuccessful) {
true -> {
val data = JSONObject(
JSONObject(
serverAnswer.body().toString()
).getString("result")
)
val userdata = UserData(
userId = data.getString("userId").toInt(),
userName = data.getString("userName"),
email = data.getString("email"),
holdingDollar = data.getString("holdingDollar")
.toFloat()
)
userid = userdata.userId
holdingDollars = userdata.holdingDollar
val intent = Intent(
context,
MainActivity::class.java
)
startActivity(context, intent, null)
}
else -> {
Log.d("Retrofit", "data null")
}
}
}
이 코드가 제대로 돌아가는 지 확인해보고 싶은데.. 이 프로젝트를 진행한지 약 10개월이 지나서 서버를 만들 동기가 이 프로젝트를 밀어버렸다고 한다..
그래서 이게 제대로 작동하는 지 알고 싶으면 다른 서버와 통신해봐야 할 것 같다.
코드를 보니 내가 이전에 email, nickname, userid, holdingdollars들을 다른 액티비티들과 같이 사용하기 위해 위의 정보를 전역변수로 바꾸어 쓰고 있었다...
이러면 나중에 비슷한 변수명을 사용할 때 문제가 생길 수 있고 전역변수를 사용하는 것은 좋은 선택이 아니기 때문에 Room을 사용해보기로 했다.
보통은 SharedPreferences를 사용했는데 Room이 Android 권장 사용이기도 하고, 지금 서버가 없어서 구현이 안 되는 부분을 로컬 데이터베이스로 커버해서 개발해보고 싶어졌다.
아마 다음은 Room 설치 및 사용방법에 대한 글이 될 것 같다.