diff --git a/Homework/Handnew04/RxStudy/app/build.gradle b/Homework/Handnew04/RxStudy/app/build.gradle
index 54d6ebf..317e78d 100644
--- a/Homework/Handnew04/RxStudy/app/build.gradle
+++ b/Homework/Handnew04/RxStudy/app/build.gradle
@@ -16,6 +16,8 @@ android {
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ buildConfigField("String", "BASE_URL", '"https://r5670326j8.execute-api.ap-northeast-2.amazonaws.com/delivery_server/"')
}
buildTypes {
@@ -43,7 +45,20 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
+ //rxJava
implementation 'com.jakewharton.rxbinding3:rxbinding:3.1.0'
+ //retrofit2
+ implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+ implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
+ implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
+ //okHttp
+ implementation 'com.squareup.okhttp3:okhttp:4.9.1'
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
+ //room
+ implementation 'androidx.room:room-runtime:2.4.2'
+ implementation 'androidx.room:room-ktx:2.4.2'
+ implementation 'androidx.room:room-rxjava2:2.4.2'
+ kapt 'androidx.room:room-compiler:2.4.2'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
diff --git a/Homework/Handnew04/RxStudy/app/src/main/AndroidManifest.xml b/Homework/Handnew04/RxStudy/app/src/main/AndroidManifest.xml
index ed7bb70..a8b9128 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/AndroidManifest.xml
+++ b/Homework/Handnew04/RxStudy/app/src/main/AndroidManifest.xml
@@ -1,31 +1,35 @@
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.example.rxstudy">
-
-
-
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/DefaultObserver.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/DefaultObserver.kt
similarity index 61%
rename from Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/DefaultObserver.kt
rename to Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/DefaultObserver.kt
index 909e784..b06502a 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/DefaultObserver.kt
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/DefaultObserver.kt
@@ -1,4 +1,4 @@
-package com.example.rxstudy.observerpattern
+package com.example.observerpattern
interface DefaultObserver {
fun notifyDataIsArrived(value : T)
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/DefaultSubject.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/DefaultSubject.kt
similarity index 94%
rename from Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/DefaultSubject.kt
rename to Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/DefaultSubject.kt
index a5d1bdc..cc45164 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/DefaultSubject.kt
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/DefaultSubject.kt
@@ -1,4 +1,4 @@
-package com.example.rxstudy.observerpattern
+package com.example.observerpattern
import java.util.ArrayList
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/ObserverPatternActivity.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/ObserverPatternActivity.kt
similarity index 81%
rename from Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/ObserverPatternActivity.kt
rename to Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/ObserverPatternActivity.kt
index f690320..9102e24 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/ObserverPatternActivity.kt
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/ObserverPatternActivity.kt
@@ -1,9 +1,9 @@
-package com.example.rxstudy.observerpattern.ui
+package com.example.observerpattern.ui
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.example.rxstudy.R
-import com.example.rxstudy.observerpattern.DefaultSubject
+import com.example.observerpattern.DefaultSubject
class ObserverPatternActivity : AppCompatActivity() {
companion object {
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentEditText.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentEditText.kt
similarity index 91%
rename from Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentEditText.kt
rename to Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentEditText.kt
index 7969543..98e9fdc 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentEditText.kt
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentEditText.kt
@@ -1,10 +1,10 @@
-package com.example.rxstudy.observerpattern.ui
+package com.example.observerpattern.ui
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatEditText
import androidx.core.widget.doAfterTextChanged
-import com.example.rxstudy.observerpattern.DefaultObserver
+import com.example.observerpattern.DefaultObserver
class PercentEditText : AppCompatEditText, DefaultObserver {
constructor(context: Context) : super(context)
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentSeekBar.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentSeekBar.kt
similarity index 90%
rename from Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentSeekBar.kt
rename to Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentSeekBar.kt
index f96f726..e52a682 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentSeekBar.kt
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentSeekBar.kt
@@ -1,10 +1,10 @@
-package com.example.rxstudy.observerpattern.ui
+package com.example.observerpattern.ui
import android.content.Context
import android.util.AttributeSet
import android.widget.SeekBar
import androidx.appcompat.widget.AppCompatSeekBar
-import com.example.rxstudy.observerpattern.DefaultObserver
+import com.example.observerpattern.DefaultObserver
class PercentSeekBar : AppCompatSeekBar, DefaultObserver {
constructor(context: Context) : super(context)
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentTextView.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentTextView.kt
similarity index 86%
rename from Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentTextView.kt
rename to Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentTextView.kt
index e5480c0..67f7d45 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/observerpattern/ui/PercentTextView.kt
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/observerpattern/ui/PercentTextView.kt
@@ -1,10 +1,10 @@
-package com.example.rxstudy.observerpattern.ui
+package com.example.observerpattern.ui
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView
-import com.example.rxstudy.observerpattern.DefaultObserver
+import com.example.observerpattern.DefaultObserver
class PercentTextView : AppCompatTextView, DefaultObserver {
constructor(context: Context) : super(context)
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/MainActivity.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/MainActivity.kt
index 71f2fa5..6a5038c 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/MainActivity.kt
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/MainActivity.kt
@@ -1,10 +1,11 @@
package com.example.rxstudy
import android.content.Intent
-import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
-import com.example.rxstudy.observerpattern.ui.ObserverPatternActivity
+import androidx.appcompat.app.AppCompatActivity
+import com.example.observerpattern.ui.ObserverPatternActivity
+import com.example.rxstudy.login.ui.LoginExampleActivity
import com.example.rxstudy.operator.FlowControlOperatorSampleActivity
import com.example.rxstudy.rxbinding.RxBindingSampleActivity
import com.example.rxstudy.scheduler.SchedulerSampleActivity
@@ -14,6 +15,7 @@ class MainActivity : AppCompatActivity() {
private lateinit var schedulerSampleButton: Button
private lateinit var flowOperatorButton: Button
private lateinit var rxBindingSampleButton: Button
+ private val loginExampleButton: Button by lazy { findViewById(R.id.bt_login_example) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -47,5 +49,10 @@ class MainActivity : AppCompatActivity() {
val intent = Intent(this@MainActivity, RxBindingSampleActivity::class.java)
startActivity(intent)
}
+
+ loginExampleButton.setOnClickListener {
+ val intent = Intent(this@MainActivity, LoginExampleActivity::class.java)
+ startActivity(intent)
+ }
}
}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/RxApplication.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/RxApplication.kt
new file mode 100644
index 0000000..2763fee
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/RxApplication.kt
@@ -0,0 +1,18 @@
+package com.example.rxstudy
+
+import android.app.Application
+import com.example.rxstudy.login.data.local.DatabaseClient
+import io.reactivex.exceptions.UndeliverableException
+import io.reactivex.plugins.RxJavaPlugins
+
+class RxApplication: Application() {
+ override fun onCreate() {
+ super.onCreate()
+ RxJavaPlugins.setErrorHandler { e: Throwable ->
+ if (e is UndeliverableException) {
+ return@setErrorHandler
+ }
+ }
+ DatabaseClient.createDatabase(this)
+ }
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/PrefUtil.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/PrefUtil.kt
new file mode 100644
index 0000000..ec8bf9b
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/PrefUtil.kt
@@ -0,0 +1,21 @@
+package com.example.rxstudy.login
+
+import android.content.Context
+import android.content.Context.MODE_PRIVATE
+
+class PrefUtil(context: Context) {
+ companion object {
+ const val DEFAULT_VALUE = ""
+ const val PREF_DEFAULT = "PREF_DEFAULT"
+ const val ACCESS_TOKEN = "LOGIN_TOKEN"
+ }
+
+ private val sharedPref = context.getSharedPreferences(PREF_DEFAULT, MODE_PRIVATE)
+ private fun getEdit() = sharedPref.edit()
+
+ fun saveToken(token: String) {
+ getEdit().putString(ACCESS_TOKEN, token).apply()
+ }
+
+ fun getToken() = sharedPref.getString(ACCESS_TOKEN, DEFAULT_VALUE)
+}
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/AppDatabase.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/AppDatabase.kt
new file mode 100644
index 0000000..110df70
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/AppDatabase.kt
@@ -0,0 +1,11 @@
+package com.example.rxstudy.login.data.local
+
+import androidx.room.Database
+import androidx.room.RoomDatabase
+import com.example.rxstudy.login.data.local.token.LocalTokenDao
+import com.example.rxstudy.login.data.local.token.LocalTokenItem
+
+@Database(entities = [LocalTokenItem::class], version = 1)
+abstract class AppDatabase: RoomDatabase() {
+ abstract fun localTokenDao(): LocalTokenDao
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/DatabaseClient.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/DatabaseClient.kt
new file mode 100644
index 0000000..5d5af25
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/DatabaseClient.kt
@@ -0,0 +1,19 @@
+package com.example.rxstudy.login.data.local
+
+import android.content.Context
+import androidx.room.Room
+import com.example.rxstudy.login.data.local.token.LocalTokenDao
+
+object DatabaseClient {
+ private lateinit var appDatabase: AppDatabase
+
+ fun createDatabase(context: Context) {
+ appDatabase = Room.databaseBuilder(
+ context.applicationContext,
+ AppDatabase::class.java,
+ "database"
+ ).build()
+ }
+
+ fun tokenDao(): LocalTokenDao = appDatabase.localTokenDao()
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDao.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDao.kt
new file mode 100644
index 0000000..403407a
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDao.kt
@@ -0,0 +1,28 @@
+package com.example.rxstudy.login.data.local.token
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.Query
+import io.reactivex.Completable
+import io.reactivex.Single
+
+@Dao
+interface LocalTokenDao {
+ @Query(value = "SELECT * FROM token LIMIT 1")
+ fun getToken(): Single
+
+ @Insert
+ fun saveToken(tokenItem: LocalTokenItem): Completable
+
+ @Query(value = "DELETE FROM token")
+ fun deleteAllCachedToken(): Completable
+
+ @Query(value = "SELECT * FROM token LIMIT 1")
+ fun getTokenNotRx(): LocalTokenItem
+
+ @Insert
+ fun saveTokenNotRx(tokenItem: LocalTokenItem)
+
+ @Query(value = "DELETE FROM token")
+ fun deleteAllCachedTokenNotRx()
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDataSource.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDataSource.kt
new file mode 100644
index 0000000..d2472f9
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDataSource.kt
@@ -0,0 +1,13 @@
+package com.example.rxstudy.login.data.local.token
+
+import io.reactivex.Completable
+import io.reactivex.Single
+
+interface LocalTokenDataSource {
+ fun getToken(): Single
+ fun saveToken(tokenItem: LocalTokenItem): Completable
+ fun deleteAllCachedToken(): Completable
+ fun getTokenNotRx(): LocalTokenItem
+ fun saveTokenNotRx(tokenItem: LocalTokenItem)
+ fun deleteAllCachedTokenNotRx()
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDataSourceImpl.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDataSourceImpl.kt
new file mode 100644
index 0000000..ce525cd
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenDataSourceImpl.kt
@@ -0,0 +1,40 @@
+package com.example.rxstudy.login.data.local.token
+
+import io.reactivex.Completable
+import io.reactivex.Single
+import io.reactivex.schedulers.Schedulers
+
+class LocalTokenDataSourceImpl(private val localTokenDao: LocalTokenDao) : LocalTokenDataSource {
+ override fun getToken(): Single {
+ return localTokenDao
+ .getToken()
+ .subscribeOn(Schedulers.io())
+ }
+
+ override fun saveToken(tokenItem: LocalTokenItem): Completable {
+ return localTokenDao
+ .saveToken(tokenItem)
+ .subscribeOn(Schedulers.io())
+ }
+
+ override fun deleteAllCachedToken(): Completable {
+ return localTokenDao
+ .deleteAllCachedToken()
+ .subscribeOn(Schedulers.io())
+ }
+
+ override fun getTokenNotRx(): LocalTokenItem {
+ return localTokenDao
+ .getTokenNotRx()
+ }
+
+ override fun saveTokenNotRx(tokenItem: LocalTokenItem) {
+ return localTokenDao
+ .saveTokenNotRx(tokenItem)
+ }
+
+ override fun deleteAllCachedTokenNotRx() {
+ return localTokenDao
+ .deleteAllCachedTokenNotRx()
+ }
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenItem.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenItem.kt
new file mode 100644
index 0000000..c68ca20
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenItem.kt
@@ -0,0 +1,12 @@
+package com.example.rxstudy.login.data.local.token
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "token")
+data class LocalTokenItem(
+ @PrimaryKey(autoGenerate = true) val idx: Int = 0,
+ @ColumnInfo(name = "accessToken") val accessToken: String,
+ @ColumnInfo(name = "refreshToken") val refreshToken: String
+)
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenMapper.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenMapper.kt
new file mode 100644
index 0000000..17c8de3
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/local/token/LocalTokenMapper.kt
@@ -0,0 +1,12 @@
+package com.example.rxstudy.login.data.local.token
+
+import com.example.rxstudy.login.data.remote.login.LoginItem
+
+object LocalTokenMapper {
+ fun mappingRemoteDataToLocal(loginItem: LoginItem): LocalTokenItem {
+ return LocalTokenItem(
+ accessToken = loginItem.access,
+ refreshToken = loginItem.refresh
+ )
+ }
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/RetrofitClient.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/RetrofitClient.kt
new file mode 100644
index 0000000..4c16e12
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/RetrofitClient.kt
@@ -0,0 +1,36 @@
+package com.example.rxstudy.login.data.remote
+
+import com.example.rxstudy.BuildConfig
+import com.example.rxstudy.login.data.remote.login.LoginApi
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
+import retrofit2.converter.gson.GsonConverterFactory
+
+object RetrofitClient {
+ private const val baseURL = BuildConfig.BASE_URL
+
+ private val okHttpClient: OkHttpClient by lazy {
+ return@lazy OkHttpClient
+ .Builder()
+ .addInterceptor(HttpLoggingInterceptor().apply {
+ level = HttpLoggingInterceptor.Level.BODY
+ })
+ .build()
+ }
+
+ private val buildRetrofitClient: Retrofit by lazy {
+ return@lazy Retrofit
+ .Builder()
+ .baseUrl(baseURL)
+ .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
+ .addConverterFactory(GsonConverterFactory.create())
+ .client(okHttpClient)
+ .build()
+ }
+
+ val loginApi: LoginApi by lazy {
+ return@lazy buildRetrofitClient.create(LoginApi::class.java)
+ }
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseAPICallResult.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseAPICallResult.kt
new file mode 100644
index 0000000..ffa3fa0
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseAPICallResult.kt
@@ -0,0 +1,6 @@
+package com.example.rxstudy.login.data.remote.base
+
+data class BaseAPICallResult(
+ val result: T? = null,
+ val throwable: Throwable? = null
+)
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseAPICallTransformer.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseAPICallTransformer.kt
new file mode 100644
index 0000000..3399f01
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseAPICallTransformer.kt
@@ -0,0 +1,17 @@
+package com.example.rxstudy.login.data.remote.base
+
+import io.reactivex.Completable
+import io.reactivex.Single
+import io.reactivex.SingleTransformer
+
+fun Completable.transformCompletableToSingleDefault(): Single> =
+ toSingleDefault(Unit).compose(wrappingSingleAPIResultData())
+
+fun Single.wrappingAPICallResult(): Single> =
+ compose(wrappingSingleAPIResultData())
+
+fun wrappingSingleAPIResultData() = SingleTransformer> { single ->
+ single
+ .map { data -> BaseAPICallResult(result = data) }
+ .onErrorReturn { BaseAPICallResult(throwable = it) }
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseCallback.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseCallback.kt
new file mode 100644
index 0000000..1b74c78
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/base/BaseCallback.kt
@@ -0,0 +1,6 @@
+package com.example.rxstudy.login.data.remote.base
+
+interface BaseCallback {
+ fun onSuccess(data: T)
+ fun onFail(throwable: Throwable)
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginApi.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginApi.kt
new file mode 100644
index 0000000..a5926de
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginApi.kt
@@ -0,0 +1,14 @@
+package com.example.rxstudy.login.data.remote.login
+
+import io.reactivex.Single
+import retrofit2.Call
+import retrofit2.http.Body
+import retrofit2.http.POST
+
+interface LoginApi {
+ @POST("api/token/")
+ fun loginRetrofitCall(@Body loginInfo: LoginInfo): Call
+
+ @POST("api/token/")
+ fun loginRxStream(@Body loginInfo: LoginInfo): Single
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginDataSource.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginDataSource.kt
new file mode 100644
index 0000000..0be629a
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginDataSource.kt
@@ -0,0 +1,9 @@
+package com.example.rxstudy.login.data.remote.login
+
+import io.reactivex.Single
+import retrofit2.Callback
+
+interface LoginDataSource {
+ fun loginRetrofitCall(id: String, password: String, callback: Callback)
+ fun loginRxStream(id: String, password: String): Single
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginDataSourceImpl.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginDataSourceImpl.kt
new file mode 100644
index 0000000..d06e427
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginDataSourceImpl.kt
@@ -0,0 +1,19 @@
+package com.example.rxstudy.login.data.remote.login
+
+import io.reactivex.Single
+import io.reactivex.schedulers.Schedulers
+import retrofit2.Callback
+
+class LoginDataSourceImpl(private val loginApi: LoginApi) : LoginDataSource {
+ override fun loginRetrofitCall(id: String, password: String, callback: Callback) {
+ loginApi.loginRetrofitCall(LoginInfo(id, password))
+ .enqueue(callback)
+ }
+
+ override fun loginRxStream(id: String, password: String): Single {
+ return loginApi
+ .loginRxStream(LoginInfo(id, password))
+ .subscribeOn(Schedulers.io())
+ }
+
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginInfo.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginInfo.kt
new file mode 100644
index 0000000..d0ea919
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginInfo.kt
@@ -0,0 +1,6 @@
+package com.example.rxstudy.login.data.remote.login
+
+data class LoginInfo(
+ val username: String,
+ val password: String
+)
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginItem.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginItem.kt
new file mode 100644
index 0000000..c1e461b
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/remote/login/LoginItem.kt
@@ -0,0 +1,6 @@
+package com.example.rxstudy.login.data.remote.login
+
+data class LoginItem(
+ val access: String,
+ val refresh: String
+)
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/repository/login/LoginRepository.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/repository/login/LoginRepository.kt
new file mode 100644
index 0000000..b231b4d
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/repository/login/LoginRepository.kt
@@ -0,0 +1,9 @@
+package com.example.rxstudy.login.data.repository.login
+
+import com.example.rxstudy.login.data.remote.base.BaseCallback
+import io.reactivex.Completable
+
+interface LoginRepository {
+ fun loginRetrofitCall(id: String, password:String, callback: BaseCallback)
+ fun loginRxStream(id: String, password: String): Completable
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/repository/login/LoginRepositoryImpl.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/repository/login/LoginRepositoryImpl.kt
new file mode 100644
index 0000000..4ac0913
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/data/repository/login/LoginRepositoryImpl.kt
@@ -0,0 +1,55 @@
+package com.example.rxstudy.login.data.repository.login
+
+import com.example.rxstudy.login.data.local.token.LocalTokenDataSource
+import com.example.rxstudy.login.data.local.token.LocalTokenMapper.mappingRemoteDataToLocal
+import com.example.rxstudy.login.data.remote.base.BaseCallback
+import com.example.rxstudy.login.data.remote.login.LoginDataSource
+import com.example.rxstudy.login.data.remote.login.LoginItem
+import io.reactivex.Completable
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+
+class LoginRepositoryImpl(
+ private val localTokenDataSource: LocalTokenDataSource,
+ private val loginDataSource: LoginDataSource
+) : LoginRepository {
+
+ override fun loginRetrofitCall(id: String, password: String, callback: BaseCallback) {
+ loginDataSource
+ .loginRetrofitCall(id, password, object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful) {
+ try {
+ Thread {
+ localTokenDataSource
+ .deleteAllCachedTokenNotRx()
+ localTokenDataSource
+ .saveTokenNotRx(mappingRemoteDataToLocal(response.body()!!))
+ }.start()
+ } catch (e: Throwable) {
+ e.printStackTrace()
+ }
+ callback.onSuccess(Unit)
+ } else {
+ callback.onFail(Exception())
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ callback.onFail(t)
+ }
+ })
+ }
+
+ override fun loginRxStream(id: String, password: String): Completable {
+ return loginDataSource
+ .loginRxStream(id, password)
+ .flatMapCompletable {
+ localTokenDataSource
+ .deleteAllCachedToken()
+ .andThen(localTokenDataSource.saveToken(mappingRemoteDataToLocal(it)))
+ //.andThen(getFirebaseTokenSingle.ignoreElement())
+ }
+ }
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/ui/LoginExampleActivity.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/ui/LoginExampleActivity.kt
new file mode 100644
index 0000000..3e400d0
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/ui/LoginExampleActivity.kt
@@ -0,0 +1,68 @@
+package com.example.rxstudy.login.ui
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import com.example.rxstudy.databinding.ActivityExampleLoginBinding
+import com.example.rxstudy.login.data.local.DatabaseClient
+import com.example.rxstudy.login.data.local.token.LocalTokenDataSourceImpl
+import com.example.rxstudy.login.data.remote.RetrofitClient
+import com.example.rxstudy.login.data.remote.login.LoginDataSourceImpl
+import com.example.rxstudy.login.data.repository.login.LoginRepositoryImpl
+import com.jakewharton.rxbinding3.view.clicks
+import com.jakewharton.rxbinding3.widget.textChanges
+import io.reactivex.disposables.CompositeDisposable
+
+class LoginExampleActivity : AppCompatActivity() {
+ private val binding: ActivityExampleLoginBinding by lazy {
+ ActivityExampleLoginBinding.inflate(layoutInflater)
+ }
+
+ private val compositeDisposable = CompositeDisposable()
+
+ private val viewModel: LoginViewModel by lazy {
+ LoginViewModel(
+ loginRepository = LoginRepositoryImpl(
+ localTokenDataSource = LocalTokenDataSourceImpl(
+ localTokenDao = DatabaseClient.tokenDao()
+ ), loginDataSource = LoginDataSourceImpl(
+ loginApi = RetrofitClient.loginApi
+ )
+ )
+ )
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(binding.root)
+
+ setListener()
+ }
+
+ private fun setListener() {
+ val idChanges = binding.etId.textChanges()
+ val passwordChanges = binding.etPw.textChanges()
+
+ compositeDisposable.add(
+ binding.btLogin.clicks().subscribe({
+ viewModel.loginRxStream(
+ binding.etId.text.toString(), binding.etPw.text.toString()
+ )
+ }, {})
+ )
+ compositeDisposable.add(
+ viewModel.loginSuccessSubject.subscribe({ successToLogin ->
+ if (successToLogin) {
+ binding.tvResult.text = "로그인 성공"
+ } else {
+ binding.tvResult.text = "로그인 실패"
+ }
+ }, { it.printStackTrace() })
+ )
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ viewModel.onViewCleared()
+ compositeDisposable.dispose()
+ }
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/ui/LoginViewModel.kt b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/ui/LoginViewModel.kt
new file mode 100644
index 0000000..604064f
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/java/com/example/rxstudy/login/ui/LoginViewModel.kt
@@ -0,0 +1,37 @@
+package com.example.rxstudy.login.ui
+
+import com.example.rxstudy.login.data.remote.base.BaseCallback
+import com.example.rxstudy.login.data.remote.base.transformCompletableToSingleDefault
+import com.example.rxstudy.login.data.repository.login.LoginRepository
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.subjects.PublishSubject
+
+class LoginViewModel(private val loginRepository: LoginRepository) {
+ val loginSuccessSubject = PublishSubject.create()
+
+ private val loginSubject = PublishSubject.create>()
+ private val compositeDisposable = CompositeDisposable()
+
+ init {
+ compositeDisposable
+ .add(
+ loginSubject
+ .flatMapSingle {
+ loginRepository
+ .loginRxStream(it.first, it.second)
+ .transformCompletableToSingleDefault()
+ }
+ .subscribe(
+ { loginSuccessSubject.onNext(it.throwable == null) },
+ { it.printStackTrace() })
+ )
+ }
+
+ fun loginRxStream(id: String, password: String) {
+ loginSubject.onNext(Pair(id, password))
+ }
+
+ fun onViewCleared() {
+ compositeDisposable.dispose()
+ }
+}
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_example_login.xml b/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_example_login.xml
new file mode 100644
index 0000000..cbbb9d4
--- /dev/null
+++ b/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_example_login.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_main.xml b/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_main.xml
index cfd71e6..5328f7c 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_main.xml
+++ b/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_main.xml
@@ -1,6 +1,5 @@
+
+
\ No newline at end of file
diff --git a/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_pattern_observer.xml b/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_pattern_observer.xml
index d35f11e..266ea98 100644
--- a/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_pattern_observer.xml
+++ b/Homework/Handnew04/RxStudy/app/src/main/res/layout/activity_pattern_observer.xml
@@ -5,16 +5,16 @@
android:gravity="center"
android:orientation="vertical">
-
-
-
\ No newline at end of file