Skip to content

Commit 2b4cc25

Browse files
committed
[FEAT] #9 : 7차 세미나 도전과제
- Room을 사용한 자동 로그인 구현 - StateFlow 사용한 상태 갱신
1 parent 58b13d6 commit 2b4cc25

File tree

13 files changed

+194
-25
lines changed

13 files changed

+194
-25
lines changed

app/build.gradle

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ android {
4747
}
4848

4949
dependencies {
50-
implementation 'androidx.core:core-ktx:1.7.0'
51-
implementation 'androidx.appcompat:appcompat:1.4.1'
52-
implementation 'com.google.android.material:material:1.6.0'
53-
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
50+
implementation 'androidx.core:core-ktx:1.8.0'
51+
implementation 'androidx.appcompat:appcompat:1.4.2'
52+
implementation 'com.google.android.material:material:1.6.1'
53+
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
5454
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
5555
testImplementation 'junit:junit:4.13.2'
5656
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
@@ -61,8 +61,8 @@ dependencies {
6161
kapt 'androidx.room:room-compiler:2.4.2'
6262

6363
// Hilt
64-
implementation "com.google.dagger:hilt-android:2.40"
65-
kapt "com.google.dagger:hilt-android-compiler:2.40"
64+
implementation "com.google.dagger:hilt-android:2.41"
65+
kapt "com.google.dagger:hilt-android-compiler:2.41"
6666

6767
// ktx
6868
implementation 'androidx.activity:activity-ktx:1.4.0'
@@ -90,5 +90,11 @@ dependencies {
9090

9191
// OkHttp3
9292
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
93-
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
93+
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
94+
95+
// Coroutines
96+
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
97+
98+
// lifecycle
99+
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
94100
}

app/src/main/java/co/kr/sopt_seminar_30th/data/database/AppDatabase.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@ import android.content.Context
44
import androidx.room.Database
55
import androidx.room.Room
66
import androidx.room.RoomDatabase
7+
import co.kr.sopt_seminar_30th.data.datasource.local.AuthorizationDao
78
import co.kr.sopt_seminar_30th.data.datasource.local.FollowerDao
89
import co.kr.sopt_seminar_30th.data.datasource.local.RepositoryDao
910
import co.kr.sopt_seminar_30th.data.datasource.local.UserDao
11+
import co.kr.sopt_seminar_30th.data.model.dto.AuthorizationDto
1012
import co.kr.sopt_seminar_30th.data.model.dto.FollowerDto
1113
import co.kr.sopt_seminar_30th.data.model.dto.RepositoryDto
1214
import co.kr.sopt_seminar_30th.data.model.dto.UserDto
1315

14-
@Database(entities = [UserDto::class, FollowerDto::class, RepositoryDto::class], version = 1)
16+
@Database(entities = [UserDto::class, FollowerDto::class, RepositoryDto::class, AuthorizationDto::class], version = 1)
1517
abstract class AppDatabase : RoomDatabase() {
1618
abstract fun userDao(): UserDao
1719
abstract fun followerDao(): FollowerDao
1820
abstract fun repositoryDao(): RepositoryDao
21+
abstract fun authorizationDao(): AuthorizationDao
1922

2023
companion object {
2124
fun getInstance(context: Context): AppDatabase = Room
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package co.kr.sopt_seminar_30th.data.datasource.local
2+
3+
import androidx.room.*
4+
import co.kr.sopt_seminar_30th.data.model.dto.AuthorizationDto
5+
6+
@Dao
7+
interface AuthorizationDao {
8+
@Insert
9+
suspend fun insertAuthorization(authorizationDto: AuthorizationDto)
10+
11+
@Delete
12+
suspend fun deleteAuthorization(authorizationDto: AuthorizationDto)
13+
14+
@Query("SELECT * FROM Authorization WHERE userId = :id")
15+
suspend fun getAuthorization(id: String): AuthorizationDto
16+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package co.kr.sopt_seminar_30th.data.model.dto
2+
3+
import androidx.room.ColumnInfo
4+
import androidx.room.Entity
5+
import androidx.room.PrimaryKey
6+
7+
@Entity(tableName = "Authorization")
8+
data class AuthorizationDto(
9+
@PrimaryKey val userId: String,
10+
@ColumnInfo(name = "autoLogin") val autoLogin: Boolean
11+
)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package co.kr.sopt_seminar_30th.data.repositoryimpl.local
2+
3+
import co.kr.sopt_seminar_30th.data.datasource.local.AuthorizationDao
4+
import co.kr.sopt_seminar_30th.data.model.dto.AuthorizationDto
5+
import co.kr.sopt_seminar_30th.domain.repository.local.AuthorizationRepository
6+
import kotlinx.coroutines.CoroutineDispatcher
7+
import kotlinx.coroutines.withContext
8+
import javax.inject.Inject
9+
10+
class AuthorizationRepositoryImpl @Inject constructor(
11+
private val dao: AuthorizationDao,
12+
private val coroutineDispatcher: CoroutineDispatcher
13+
) : AuthorizationRepository {
14+
override suspend fun insertAuthorization(userId: String, autoLogin: Boolean) =
15+
withContext(coroutineDispatcher) {
16+
dao.insertAuthorization(AuthorizationDto(userId, autoLogin))
17+
}
18+
19+
override suspend fun deleteAuthorization(userId: String, autoLogin: Boolean) =
20+
withContext(coroutineDispatcher) {
21+
dao.deleteAuthorization(AuthorizationDto(userId, autoLogin))
22+
}
23+
24+
override suspend fun getAuthorization(userId: String): Boolean =
25+
withContext(coroutineDispatcher) {
26+
dao.getAuthorization(userId).autoLogin
27+
}
28+
}

app/src/main/java/co/kr/sopt_seminar_30th/di/DbModule.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package co.kr.sopt_seminar_30th.di
22

33
import android.content.Context
44
import co.kr.sopt_seminar_30th.data.database.AppDatabase
5+
import co.kr.sopt_seminar_30th.data.datasource.local.AuthorizationDao
56
import co.kr.sopt_seminar_30th.data.datasource.local.FollowerDao
67
import co.kr.sopt_seminar_30th.data.datasource.local.RepositoryDao
78
import co.kr.sopt_seminar_30th.data.datasource.local.UserDao
@@ -33,4 +34,8 @@ object DbModule {
3334
@Singleton
3435
@Provides
3536
fun provideRepositoryDao(appDatabase: AppDatabase): RepositoryDao = appDatabase.repositoryDao()
37+
38+
@Singleton
39+
@Provides
40+
fun provideAuthorizationDao(appDatabase: AppDatabase): AuthorizationDao = appDatabase.authorizationDao()
3641
}

app/src/main/java/co/kr/sopt_seminar_30th/di/RepositoryModule.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package co.kr.sopt_seminar_30th.di
22

3-
import co.kr.sopt_seminar_30th.data.datasource.local.FollowerDao
4-
import co.kr.sopt_seminar_30th.data.datasource.local.RepositoryDao
5-
import co.kr.sopt_seminar_30th.data.datasource.local.SopthubDataStore
6-
import co.kr.sopt_seminar_30th.data.datasource.local.UserDao
3+
import co.kr.sopt_seminar_30th.data.datasource.local.*
4+
import co.kr.sopt_seminar_30th.data.repositoryimpl.local.AuthorizationRepositoryImpl
75
import co.kr.sopt_seminar_30th.data.repositoryimpl.local.FollowerRepositoryImpl
86
import co.kr.sopt_seminar_30th.data.repositoryimpl.local.RepositoryRepositoryImpl
97
import co.kr.sopt_seminar_30th.data.repositoryimpl.local.UserRepositoryImpl
@@ -13,6 +11,7 @@ import co.kr.sopt_seminar_30th.data.repositoryimpl.remote.SignUpRepositoryImpl
1311
import co.kr.sopt_seminar_30th.data.service.auth.SignInService
1412
import co.kr.sopt_seminar_30th.data.service.auth.SignUpService
1513
import co.kr.sopt_seminar_30th.data.service.home.HomeService
14+
import co.kr.sopt_seminar_30th.domain.repository.local.AuthorizationRepository
1615
import co.kr.sopt_seminar_30th.domain.repository.local.FollowerRepository
1716
import co.kr.sopt_seminar_30th.domain.repository.local.RepositoryRepository
1817
import co.kr.sopt_seminar_30th.domain.repository.local.UserRepository
@@ -68,4 +67,12 @@ object RepositoryModule {
6867
homeService: HomeService,
6968
@IoDispatcher coroutineDispatcher: CoroutineDispatcher
7069
): HomeRepository = HomeRepositoryImpl(homeService, coroutineDispatcher)
70+
71+
@Singleton
72+
@Provides
73+
fun provideAuthorizationRepository(
74+
authorizationDao: AuthorizationDao,
75+
@IoDispatcher coroutineDispatcher: CoroutineDispatcher
76+
): AuthorizationRepository =
77+
AuthorizationRepositoryImpl(authorizationDao, coroutineDispatcher)
7178
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package co.kr.sopt_seminar_30th.domain.repository.local
2+
3+
interface AuthorizationRepository {
4+
suspend fun insertAuthorization(userId: String, autoLogin: Boolean)
5+
suspend fun deleteAuthorization(userId: String, autoLogin: Boolean)
6+
suspend fun getAuthorization(userId: String): Boolean
7+
}

app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/auth/SignInActivity.kt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,17 @@ import android.os.Bundle
55
import android.widget.Toast
66
import androidx.activity.result.contract.ActivityResultContracts
77
import androidx.activity.viewModels
8+
import androidx.lifecycle.flowWithLifecycle
9+
import androidx.lifecycle.lifecycleScope
810
import co.kr.sopt_seminar_30th.R
911
import co.kr.sopt_seminar_30th.data.datasource.local.SopthubDataStore
1012
import co.kr.sopt_seminar_30th.databinding.ActivitySignInBinding
1113
import co.kr.sopt_seminar_30th.presentation.ui.base.BaseActivity
1214
import co.kr.sopt_seminar_30th.presentation.ui.home.HomeActivity
1315
import co.kr.sopt_seminar_30th.presentation.viewmodel.SignInViewModel
1416
import dagger.hilt.android.AndroidEntryPoint
17+
import kotlinx.coroutines.flow.launchIn
18+
import kotlinx.coroutines.flow.onEach
1519
import javax.inject.Inject
1620

1721
@AndroidEntryPoint
@@ -47,8 +51,7 @@ class SignInActivity : BaseActivity<ActivitySignInBinding>() {
4751

4852
private fun loginWithAutoLogin() {
4953
if (dataStore.autoLogin) {
50-
startActivity(Intent(this, HomeActivity::class.java))
51-
finish()
54+
signInViewModel.checkAuthorization(dataStore.userId)
5255
}
5356
}
5457

@@ -95,5 +98,13 @@ class SignInActivity : BaseActivity<ActivitySignInBinding>() {
9598
Toast.makeText(this, "아이디/비밀번호를 확인해주세요", Toast.LENGTH_SHORT).show()
9699
}
97100
}
101+
signInViewModel.autoLoginState
102+
.flowWithLifecycle(this.lifecycle)
103+
.onEach {
104+
if(it) {
105+
startActivity(Intent(this, HomeActivity::class.java))
106+
finish()
107+
}
108+
}.launchIn(this.lifecycleScope)
98109
}
99110
}

app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingActivity.kt

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,61 @@ package co.kr.sopt_seminar_30th.presentation.ui.onboarding
22

33
import android.content.Intent
44
import android.os.Bundle
5+
import androidx.activity.viewModels
6+
import androidx.lifecycle.flowWithLifecycle
7+
import androidx.lifecycle.lifecycleScope
58
import co.kr.sopt_seminar_30th.R
69
import co.kr.sopt_seminar_30th.data.datasource.local.SopthubDataStore
710
import co.kr.sopt_seminar_30th.databinding.ActivityOnBoardingBinding
811
import co.kr.sopt_seminar_30th.presentation.ui.auth.SignInActivity
912
import co.kr.sopt_seminar_30th.presentation.ui.base.BaseActivity
1013
import co.kr.sopt_seminar_30th.presentation.ui.home.HomeActivity
14+
import co.kr.sopt_seminar_30th.presentation.viewmodel.OnBoardingViewModel
1115
import dagger.hilt.android.AndroidEntryPoint
16+
import kotlinx.coroutines.flow.launchIn
17+
import kotlinx.coroutines.flow.onEach
1218
import javax.inject.Inject
1319

1420
@AndroidEntryPoint
1521
class OnBoardingActivity : BaseActivity<ActivityOnBoardingBinding>() {
1622
override val layoutRes: Int
1723
get() = R.layout.activity_on_boarding
1824

25+
private val viewModel by viewModels<OnBoardingViewModel>()
26+
1927
@Inject
2028
lateinit var dataStore: SopthubDataStore
2129

2230
override fun onCreate(savedInstanceState: Bundle?) {
2331
super.onCreate(savedInstanceState)
2432
checkAutoLoginEnabled()
2533
checkOnBoardingEnabled()
34+
observeData()
2635
}
2736

2837
private fun checkAutoLoginEnabled() {
2938
if (dataStore.autoLogin) {
30-
startActivity(Intent(this, HomeActivity::class.java))
31-
finish()
39+
viewModel.checkAuthorization(dataStore.userId)
3240
}
3341
}
3442

3543
private fun checkOnBoardingEnabled() {
3644
if (dataStore.onBoardingEnabled) {
37-
if(!isFinishing) {
45+
if (!isFinishing) {
3846
startActivity(Intent(this, SignInActivity::class.java))
3947
finish()
4048
}
4149
}
4250
}
51+
52+
private fun observeData() {
53+
viewModel.autoLoginState
54+
.flowWithLifecycle(this.lifecycle)
55+
.onEach {
56+
if (it) {
57+
startActivity(Intent(this, HomeActivity::class.java))
58+
finish()
59+
}
60+
}.launchIn(this.lifecycleScope)
61+
}
4362
}

0 commit comments

Comments
 (0)