Skip to content

Commit a82d7c2

Browse files
committed
Fixing issues
1 parent f8b09a1 commit a82d7c2

8 files changed

Lines changed: 89 additions & 75 deletions

File tree

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
package com.example
22

33
import android.app.Application
4+
import com.example.example2023.BuildConfig
45
import dagger.hilt.android.HiltAndroidApp
6+
import timber.log.Timber
57

68
@HiltAndroidApp
7-
class Example2023Application : Application()
9+
class Example2023Application : Application() {
10+
11+
init {
12+
if (BuildConfig.DEBUG) {
13+
Timber.plant(Timber.DebugTree())
14+
}
15+
}
16+
}

‎2023_12/android/app/src/main/java/com/example/data/api/randomuser/RandomUserService.kt‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@ import retrofit2.http.Headers
77
import retrofit2.http.Query
88

99
interface RandomUserService {
10-
@Headers("Content-Type:application/json; Accept:application/json")
10+
11+
// Redundant as already defined when creating Retrofit instance in ApiModule
12+
@Headers(
13+
"Content-Type: application/json",
14+
"Accept: application/json"
15+
)
1116
@GET("?format=json")
12-
fun getRandomUsers(@Query("results") numberOfUsers: Int): Response<GetRandomUsersDTO>
17+
suspend fun getRandomUsers(@Query("results") numberOfUsers: Int): Response<GetRandomUsersDTO>
1318
}

‎2023_12/android/app/src/main/java/com/example/data/di/ApiModule.kt‎

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import okhttp3.Interceptor
2020
import okhttp3.MediaType.Companion.toMediaType
2121
import okhttp3.OkHttpClient
2222
import okhttp3.logging.HttpLoggingInterceptor
23-
import retrofit2.Converter
2423
import retrofit2.Retrofit
2524
import java.io.File
2625
import java.util.concurrent.TimeUnit
@@ -30,10 +29,6 @@ import kotlin.time.Duration.Companion.minutes
3029
import kotlin.time.Duration.Companion.seconds
3130
import kotlin.time.toJavaDuration
3231

33-
@Qualifier
34-
@Retention(AnnotationRetention.BINARY)
35-
annotation class JsonRetrofitConverter
36-
3732
@Qualifier
3833
@Retention(AnnotationRetention.BINARY)
3934
annotation class RandomUser
@@ -64,11 +59,6 @@ object ApiModule {
6459
@Singleton
6560
fun provideJsonSerializer() = _jsonSerializer
6661

67-
@JsonRetrofitConverter
68-
@Provides
69-
@Singleton
70-
fun provideRetrofitConverterFactory() = _jsonSerializer.asConverterFactory(contentTypeJson)
71-
7262
@Provides
7363
@Singleton
7464
fun provideCache(
@@ -119,11 +109,11 @@ object ApiModule {
119109
@Singleton
120110
@Provides
121111
fun provideRetrofitRandomUser(
122-
@JsonRetrofitConverter factory: Converter.Factory,
112+
json: Json,
123113
okHttpClient: OkHttpClient,
124114
): Retrofit = Retrofit.Builder()
125115
.baseUrl(RANDOM_USER_BASE_URL)
126-
.addConverterFactory(factory)
116+
.addConverterFactory(json.asConverterFactory(contentTypeJson))
127117
.client(okHttpClient)
128118
.build()
129119

‎2023_12/android/app/src/main/java/com/example/data/storage/migration/From0to1.kt‎

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@ package com.example.data.storage.migration
22

33
import androidx.room.migration.Migration
44
import androidx.sqlite.db.SupportSQLiteDatabase
5-
import com.example.data.storage.user.UserTable.columnFirstName
6-
import com.example.data.storage.user.UserTable.columnLastName
7-
import com.example.data.storage.user.UserTable.columnTitle
8-
import com.example.data.storage.user.UserTable.primaryKeys
95
import com.example.data.storage.user.UserTable.tableName
106
import com.example.domain.Logger
117
import javax.inject.Inject
@@ -20,27 +16,11 @@ class From0to1 @Inject constructor(
2016
}
2117

2218
private fun migrateUser(database: SupportSQLiteDatabase) {
23-
val tmpTableName = "${tableName}_tmp"
24-
val primaryKeys = primaryKeys.joinToString(separator = ",") { "`$it`" }
25-
logger.d("primaryKeys: $primaryKeys")
2619
database.execSQL(
2720
"""
28-
CREATE TABLE IF NOT EXISTS `$tmpTableName` (
29-
`$columnTitle` TEXT NOT NULL,
30-
`$columnLastName` TEXT NOT NULL,
31-
`$columnFirstName` TEXT NOT NULL,
32-
PRIMARY KEY($primaryKeys)
33-
)
21+
ALTER TABLE `$tableName`
22+
ADD COLUMN pub_year INTEGER
3423
"""
3524
)
36-
database.execSQL(
37-
"""
38-
INSERT INTO `$tmpTableName` (`$columnTitle`, `$columnFirstName`,`$columnLastName`)
39-
SELECT `$columnTitle`, `$columnFirstName`,`$columnLastName`
40-
FROM $tableName
41-
"""
42-
)
43-
database.execSQL("DROP TABLE `$tableName`")
44-
database.execSQL("ALTER TABLE `$tmpTableName` RENAME TO `$tableName`")
4525
}
4626
}

‎2023_12/android/app/src/main/java/com/example/ui/main/MainActivity.kt‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package com.example.ui.main
22

33
import android.os.Bundle
4-
import android.os.PersistableBundle
54
import androidx.activity.compose.setContent
65
import androidx.appcompat.app.AppCompatActivity
76
import dagger.hilt.android.AndroidEntryPoint
87

98
@AndroidEntryPoint
109
class MainActivity : AppCompatActivity() {
1110

12-
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
13-
super.onCreate(savedInstanceState, persistentState)
11+
override fun onCreate(savedInstanceState: Bundle?) {
12+
super.onCreate(savedInstanceState)
1413

1514
setContent {
1615
MainScreen()

‎2023_12/android/app/src/main/java/com/example/ui/main/MainCompose.kt‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ fun MainScreen(state: MainState) {
5757
@Preview(showBackground = true)
5858
@Composable
5959
fun PreviewMainScreenEmpty() {
60-
MainScreen(MainState())
60+
MainScreen(MutableMainState())
6161
}
6262

6363
@Preview(showBackground = true)
6464
@Composable
6565
fun PreviewMainScreenSuccess() {
6666
MainScreen(
67-
MainState(
67+
MutableMainState(
6868
users = listOf(
6969
User(
7070
UserTitle.MISS,
@@ -89,13 +89,13 @@ fun PreviewMainScreenSuccess() {
8989
@Preview(showBackground = true)
9090
@Composable
9191
fun PreviewMainScreenFetchError() {
92-
MainScreen(MainState(userFetchError = "No Internet connection"))
92+
MainScreen(MutableMainState(userFetchError = "No Internet connection"))
9393
}
9494

9595
@Preview(showBackground = true)
9696
@Composable
9797
fun PreviewMainScreenSaveError() {
98-
MainScreen(MainState(userSaveError = "Out of memory"))
98+
MainScreen(MutableMainState(userSaveError = "Out of memory"))
9999
}
100100

101101
@Preview(showBackground = true)

‎2023_12/android/app/src/main/java/com/example/ui/main/MainState.kt‎

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,46 @@ package com.example.ui.main
33
import com.example.domain.model.User
44
import com.example.domain.state.State
55

6-
data class MainState(
7-
val users: List<User> = emptyList(),
8-
val userFetchError: String? = null,
9-
val userSaveError: String? = null,
10-
) : State
6+
interface MainState : State {
7+
val users: List<User>
8+
val userFetchError: String?
9+
val userSaveError: String?
10+
}
11+
12+
class MutableMainState(
13+
users: List<User> = emptyList(),
14+
userFetchError: String? = null,
15+
userSaveError: String? = null,
16+
) : MainState {
17+
18+
override var users: List<User> = users
19+
set(value) {
20+
if (userFetchError != null) {
21+
userFetchError = null
22+
}
23+
if (userSaveError != null) {
24+
userSaveError = null
25+
}
26+
if (field != value) {
27+
field = value
28+
}
29+
}
30+
31+
override var userFetchError: String? = userFetchError
32+
set(value) {
33+
if (field != value) {
34+
users = emptyList()
35+
userSaveError = null
36+
field = value
37+
}
38+
}
39+
40+
override var userSaveError: String? = userSaveError
41+
set(value) {
42+
if (field != value) {
43+
users = emptyList()
44+
userFetchError = null
45+
field = value
46+
}
47+
}
48+
}

‎2023_12/android/app/src/main/java/com/example/ui/main/MainViewModelImpl.kt‎

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.example.ui.main
22

33
import androidx.lifecycle.ViewModel
44
import androidx.lifecycle.viewModelScope
5+
import com.example.domain.Logger
56
import com.example.domain.model.User
67
import com.example.domain.randomuser.GetRandomUsersUseCase
78
import com.example.domain.randomuser.SaveUserUseCase
@@ -18,13 +19,10 @@ import javax.inject.Inject
1819
class MainViewModelImpl @Inject constructor(
1920
private val getRandomUsersUseCase: GetRandomUsersUseCase,
2021
private val saveUserUseCase: SaveUserUseCase,
22+
private val logger: Logger,
2123
) : ViewModel(), MainViewModel {
2224

23-
private var mainState = MainState()
24-
set(value) {
25-
field = value
26-
_state.value = ScreenState.View(value)
27-
}
25+
private var mainState = MutableMainState()
2826

2927
private val _state = MutableStateFlow<ScreenState<MainState>>(ScreenState.Initializing)
3028

@@ -33,10 +31,15 @@ class MainViewModelImpl @Inject constructor(
3331

3432
init {
3533
viewModelScope.launch {
36-
when (val result = getRandomUsersUseCase.fetch(10)) {
37-
RemoteRequestState.Empty -> mainState = mainState.copy(users = emptyList())
38-
is RemoteRequestState.Success -> mainState = mainState.copy(users = result.data)
34+
_state.value = when (val result = getRandomUsersUseCase.fetch(10)) {
35+
RemoteRequestState.Empty ->
36+
ScreenState.View(mainState.apply { users = emptyList() })
37+
38+
is RemoteRequestState.Success ->
39+
ScreenState.View(mainState.apply { users = result.data })
40+
3941
is RemoteRequestState.Error -> ScreenState.Error(message = getErrorMsg(result))
42+
.also { logger.e("Error while fetching users at the init", result.ex) }
4043
}
4144
}
4245
}
@@ -48,22 +51,17 @@ class MainViewModelImpl @Inject constructor(
4851
} ?: "Error code: ${result.reason.name}"
4952

5053
override suspend fun fetchRandomUsers(nbUsers: Int) {
51-
mainState = when (val result = getRandomUsersUseCase.fetch(nbUsers)) {
52-
RemoteRequestState.Empty -> emptyList<User>() to null
53-
is RemoteRequestState.Success -> result.data to null
54-
is RemoteRequestState.Error -> emptyList<User>() to getErrorMsg(result)
55-
}.let { (users, fetchError) ->
56-
mainState.copy(
57-
users = users,
58-
userFetchError = fetchError,
59-
userSaveError = null,
60-
)
61-
}
54+
_state.value = when (val result = getRandomUsersUseCase.fetch(nbUsers)) {
55+
RemoteRequestState.Empty -> mainState.apply { users = emptyList() }
56+
is RemoteRequestState.Success -> mainState.apply { users = result.data }
57+
is RemoteRequestState.Error -> mainState.apply { userFetchError = getErrorMsg(result) }
58+
.also { logger.e("Error while fetching users", result.ex) }
59+
}.let { ScreenState.View(it) }
6260
}
6361

6462
override suspend fun saveUser(user: User) {
6563
val defaultErrorMsg = "Unknown error"
66-
mainState = when (val result = saveUserUseCase.save(user)) {
64+
when (val result = saveUserUseCase.save(user)) {
6765
is LocalRequestState.Create,
6866
is LocalRequestState.Read,
6967
is LocalRequestState.Update,
@@ -73,11 +71,6 @@ class MainViewModelImpl @Inject constructor(
7371
is LocalRequestState.ErrorRead -> result.e?.message ?: defaultErrorMsg
7472
is LocalRequestState.ErrorUpdate -> result.e?.message ?: defaultErrorMsg
7573
is LocalRequestState.ErrorDelete -> result.e?.message ?: defaultErrorMsg
76-
}.let {
77-
mainState.copy(
78-
userFetchError = null,
79-
userSaveError = it,
80-
)
81-
}
74+
}?.let { _state.value = ScreenState.View(mainState.apply { userSaveError = it }) }
8275
}
8376
}

0 commit comments

Comments
 (0)