Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3c5404b

Browse files
add @relation and @Embedded to PostEntity and implementations
1 parent c1b494b commit 3c5404b

File tree

17 files changed

+519
-62
lines changed

17 files changed

+519
-62
lines changed

‎app/src/main/java/com/smarttoolfactory/postdynamichilt/postlist/PostListFragment.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class PostListFragment : DynamicNavigationFragment<FragmentPostListBinding>() {
1616

1717
override fun getLayoutRes(): Int = R.layout.fragment_post_list
1818

19-
private val viewModel: PostListViewModel by viewModels()
19+
// private val viewModel: PostListViewModel by viewModels()
20+
private val viewModel: PostStatusViewModel by viewModels()
2021

2122
private lateinit var postListAdapter: PostListAdapter
2223

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.smarttoolfactory.postdynamichilt.postlist
2+
3+
import androidx.hilt.Assisted
4+
import androidx.hilt.lifecycle.ViewModelInject
5+
import androidx.lifecycle.LiveData
6+
import androidx.lifecycle.SavedStateHandle
7+
import com.smarttoolfactory.core.util.Event
8+
import com.smarttoolfactory.core.util.convertToFlowViewState
9+
import com.smarttoolfactory.core.viewstate.Status
10+
import com.smarttoolfactory.core.viewstate.ViewState
11+
import com.smarttoolfactory.domain.model.Post
12+
import com.smarttoolfactory.domain.usecase.GetPostsWithStatusUseCaseFlow
13+
import kotlinx.coroutines.CoroutineScope
14+
import kotlinx.coroutines.flow.launchIn
15+
import kotlinx.coroutines.flow.onEach
16+
import kotlinx.coroutines.flow.onStart
17+
18+
class PostStatusViewModel @ViewModelInject constructor(
19+
private val coroutineScope: CoroutineScope,
20+
private val getPostsUseCase: GetPostsWithStatusUseCaseFlow,
21+
@Assisted savedStateHandle: SavedStateHandle
22+
) : AbstractPostListVM() {
23+
24+
private val _goToDetailScreen =
25+
savedStateHandle.getLiveData<Event<Post>>(POST_DETAIL)
26+
27+
override val goToDetailScreen: LiveData<Event<Post>>
28+
get() = _goToDetailScreen
29+
30+
private val _postViewState =
31+
savedStateHandle.getLiveData<ViewState<List<Post>>>(POST_LIST)
32+
33+
override val postViewState: LiveData<ViewState<List<Post>>>
34+
get() = _postViewState
35+
36+
/**
37+
* Function to retrieve data from repository with offline-first which checks
38+
* local data source first.
39+
*
40+
* * Check out Local Source first
41+
* * If empty data or null returned throw empty set exception
42+
* * If error occurred while fetching data from remote: Try to fetch data from db
43+
* * If data is fetched from remote source: delete old data, save new data and return new data
44+
* * If both network and db don't have any data throw empty set exception
45+
*
46+
*/
47+
override fun getPosts() {
48+
49+
getPostsUseCase.getPostFlowOfflineFirst()
50+
.convertToFlowViewState()
51+
.onStart {
52+
_postViewState.value = ViewState(status = Status.LOADING)
53+
}
54+
.onEach {
55+
_postViewState.value = it
56+
}
57+
.launchIn(coroutineScope)
58+
}
59+
60+
override fun refreshPosts() {
61+
getPostsUseCase.getPostFlowOfflineLast()
62+
.convertToFlowViewState()
63+
.onStart {
64+
_postViewState.value = ViewState(status = Status.LOADING)
65+
}
66+
.onEach {
67+
_postViewState.value = it
68+
}
69+
.launchIn(coroutineScope)
70+
}
71+
72+
override fun onClick(post: Post) {
73+
_goToDetailScreen.value = Event(post)
74+
}
75+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
{
2+
"formatVersion": 1,
3+
"database": {
4+
"version": 2,
5+
"identityHash": "b146a82a326ba2e588d49914b9f527b2",
6+
"entities": [
7+
{
8+
"tableName": "post",
9+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `userId` INTEGER NOT NULL, `title` TEXT NOT NULL, `body` TEXT NOT NULL, PRIMARY KEY(`id`))",
10+
"fields": [
11+
{
12+
"fieldPath": "id",
13+
"columnName": "id",
14+
"affinity": "INTEGER",
15+
"notNull": true
16+
},
17+
{
18+
"fieldPath": "userId",
19+
"columnName": "userId",
20+
"affinity": "INTEGER",
21+
"notNull": true
22+
},
23+
{
24+
"fieldPath": "title",
25+
"columnName": "title",
26+
"affinity": "TEXT",
27+
"notNull": true
28+
},
29+
{
30+
"fieldPath": "body",
31+
"columnName": "body",
32+
"affinity": "TEXT",
33+
"notNull": true
34+
}
35+
],
36+
"primaryKey": {
37+
"columnNames": [
38+
"id"
39+
],
40+
"autoGenerate": false
41+
},
42+
"indices": [],
43+
"foreignKeys": []
44+
},
45+
{
46+
"tableName": "post_status",
47+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `userAccountId` INTEGER NOT NULL, `postId` INTEGER NOT NULL, `displayCount` INTEGER NOT NULL, `isFavorite` INTEGER NOT NULL, FOREIGN KEY(`postId`) REFERENCES `post`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
48+
"fields": [
49+
{
50+
"fieldPath": "id",
51+
"columnName": "id",
52+
"affinity": "INTEGER",
53+
"notNull": true
54+
},
55+
{
56+
"fieldPath": "userAccountId",
57+
"columnName": "userAccountId",
58+
"affinity": "INTEGER",
59+
"notNull": true
60+
},
61+
{
62+
"fieldPath": "postId",
63+
"columnName": "postId",
64+
"affinity": "INTEGER",
65+
"notNull": true
66+
},
67+
{
68+
"fieldPath": "displayCount",
69+
"columnName": "displayCount",
70+
"affinity": "INTEGER",
71+
"notNull": true
72+
},
73+
{
74+
"fieldPath": "isFavorite",
75+
"columnName": "isFavorite",
76+
"affinity": "INTEGER",
77+
"notNull": true
78+
}
79+
],
80+
"primaryKey": {
81+
"columnNames": [
82+
"id"
83+
],
84+
"autoGenerate": true
85+
},
86+
"indices": [
87+
{
88+
"name": "index_post_status_userAccountId_postId",
89+
"unique": false,
90+
"columnNames": [
91+
"userAccountId",
92+
"postId"
93+
],
94+
"createSql": "CREATE INDEX IF NOT EXISTS `index_post_status_userAccountId_postId` ON `${TABLE_NAME}` (`userAccountId`, `postId`)"
95+
}
96+
],
97+
"foreignKeys": [
98+
{
99+
"table": "post",
100+
"onDelete": "NO ACTION",
101+
"onUpdate": "NO ACTION",
102+
"columns": [
103+
"postId"
104+
],
105+
"referencedColumns": [
106+
"id"
107+
]
108+
}
109+
]
110+
}
111+
],
112+
"views": [],
113+
"setupQueries": [
114+
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
115+
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'b146a82a326ba2e588d49914b9f527b2')"
116+
]
117+
}
118+
}

‎libraries/data/src/main/java/com/smarttoolfactory/data/db/PostDaoCoroutines.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import androidx.room.Delete
55
import androidx.room.Insert
66
import androidx.room.OnConflictStrategy
77
import androidx.room.Query
8-
import androidx.room.Update
98
import com.smarttoolfactory.data.model.PostEntity
109
import kotlinx.coroutines.flow.Flow
1110

@@ -36,7 +35,6 @@ interface PostDaoCoroutines {
3635
*
3736
* *If database is empty returns empty list []
3837
*/
39-
// Suspend
4038
@Query("SELECT * FROM post")
4139
suspend fun getPostList(): List<PostEntity>
4240

@@ -58,12 +56,6 @@ interface PostDaoCoroutines {
5856
// @Query("SELECT * FROM post ORDER BY displayCount DESC")
5957
// suspend fun getDisplayedMostPosts(): List<PostEntity>
6058

61-
/**
62-
* Update a post's favorite or display count status.
63-
*/
64-
@Update
65-
suspend fun updatePostFavoriteOrSelectStatus(postEntity: PostEntity)
66-
6759
/*
6860
***** Flow ******
6961
*/

‎libraries/data/src/main/java/com/smarttoolfactory/data/db/PostDatabase.kt

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,42 @@ package com.smarttoolfactory.data.db
22

33
import androidx.room.Database
44
import androidx.room.RoomDatabase
5-
import com.smarttoolfactory.data.model.PostAttention
5+
import androidx.room.migration.Migration
6+
import androidx.sqlite.db.SupportSQLiteDatabase
67
import com.smarttoolfactory.data.model.PostEntity
8+
import com.smarttoolfactory.data.model.PostStatus
79

810
const val DATABASE_NAME = "post.db"
911

1012
@Database(
11-
entities = [PostEntity::class, PostAttention::class],
12-
version = 1,
13+
entities = [PostEntity::class, PostStatus::class],
14+
version = 2,
1315
exportSchema = true
1416
)
1517
abstract class PostDatabase : RoomDatabase() {
1618
abstract fun postDao(): PostDaoCoroutines
1719
abstract fun postDaoRxJava(): PostDaoRxJava3
20+
abstract fun postStatusDao(): PostStatusDao
1821
}
1922

20-
/*
2123
val MIGRATION_1_2: Migration = object : Migration(1, 2) {
2224

2325
override fun migrate(database: SupportSQLiteDatabase) {
26+
2427
database.execSQL(
25-
"ALTER TABLE post ADD COLUMN displayCount INTEGER NOT NULL DEFAULT 0"
28+
"CREATE TABLE IF NOT EXISTS post_status " +
29+
"(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " +
30+
"userAccountId INTEGER NOT NULL, " +
31+
"postId INTEGER NOT NULL, " +
32+
"displayCount INTEGER NOT NULL, " +
33+
"isFavorite INTEGER NOT NULL, " +
34+
"FOREIGN KEY(postId) REFERENCES post(id) " +
35+
"ON UPDATE NO ACTION ON DELETE NO ACTION )"
2636
)
2737

2838
database.execSQL(
29-
"ALTER TABLE post ADD COLUMN isFavorite INTEGER NOT NULL DEFAULT 0"
39+
"CREATE INDEX IF NOT EXISTS index_post_status_postId " +
40+
"ON post_status (userAccountId, postId)"
3041
)
3142
}
32-
}
33-
*/
43+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.smarttoolfactory.data.db
2+
3+
import androidx.room.Dao
4+
import androidx.room.Embedded
5+
import androidx.room.Query
6+
import androidx.room.Relation
7+
import androidx.room.Transaction
8+
import com.smarttoolfactory.data.model.PostAndStatus
9+
import com.smarttoolfactory.data.model.PostEntity
10+
import com.smarttoolfactory.data.model.PostStatus
11+
12+
@Dao
13+
interface PostStatusDao {
14+
15+
/**
16+
* Update a post's favorite or display count status.
17+
*/
18+
// @Update
19+
// suspend fun updatePostStatus(postStatus: PostStatus)
20+
21+
/**
22+
* This method uses [Embedded] and [Relation] annotations to create a class that contains
23+
* [PostEntity] and [PostStatus] which is display count and like belong to this [PostEntity]
24+
* by a specific account that is currently logged in
25+
*/
26+
@Transaction
27+
@Query("SELECT * FROM post")
28+
suspend fun getPostWithStatus(): List<PostAndStatus>
29+
}

‎libraries/data/src/main/java/com/smarttoolfactory/data/di/DataModule.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ import com.smarttoolfactory.data.repository.PostRepositoryCoroutines
55
import com.smarttoolfactory.data.repository.PostRepositoryCoroutinesImpl
66
import com.smarttoolfactory.data.repository.PostRepositoryRxJava3
77
import com.smarttoolfactory.data.repository.PostRepositoryRxJava3Impl
8+
import com.smarttoolfactory.data.repository.PostStatusRepository
9+
import com.smarttoolfactory.data.repository.PostStatusRepositoryImpl
810
import com.smarttoolfactory.data.source.LocalDataSourceRxJava3Impl
911
import com.smarttoolfactory.data.source.LocalPostDataSourceCoroutines
1012
import com.smarttoolfactory.data.source.LocalPostDataSourceCoroutinesImpl
1113
import com.smarttoolfactory.data.source.LocalPostDataSourceRxJava3
14+
import com.smarttoolfactory.data.source.LocalPostStatusSource
15+
import com.smarttoolfactory.data.source.LocalPostStatusSourceImpl
1216
import com.smarttoolfactory.data.source.RemoteDataSourceRxJava3Impl
1317
import com.smarttoolfactory.data.source.RemotePostDataSourceCoroutines
1418
import com.smarttoolfactory.data.source.RemotePostDataSourceCoroutinesImpl
@@ -59,6 +63,19 @@ interface DataModule {
5963
@Binds
6064
fun bindRepositoryRxJava3(repository: PostRepositoryRxJava3Impl):
6165
PostRepositoryRxJava3
66+
67+
/*
68+
Post Status
69+
*/
70+
@Singleton
71+
@Binds
72+
fun bindLocalPostStatusSource(localDataSource: LocalPostStatusSourceImpl):
73+
LocalPostStatusSource
74+
75+
@Singleton
76+
@Binds
77+
fun bindPostStatusRepository(repository: PostStatusRepositoryImpl):
78+
PostStatusRepository
6279
}
6380

6481
/**

‎libraries/data/src/main/java/com/smarttoolfactory/data/di/DatabaseModule.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package com.smarttoolfactory.data.di
33
import android.app.Application
44
import androidx.room.Room
55
import com.smarttoolfactory.data.db.DATABASE_NAME
6+
import com.smarttoolfactory.data.db.MIGRATION_1_2
67
import com.smarttoolfactory.data.db.PostDaoCoroutines
78
import com.smarttoolfactory.data.db.PostDaoRxJava3
89
import com.smarttoolfactory.data.db.PostDatabase
10+
import com.smarttoolfactory.data.db.PostStatusDao
911
import dagger.Module
1012
import dagger.Provides
1113
import dagger.hilt.InstallIn
@@ -24,18 +26,18 @@ class DatabaseModule {
2426
PostDatabase::class.java,
2527
DATABASE_NAME
2628
)
27-
// .addMigrations(MIGRATION_1_2)
29+
.addMigrations(MIGRATION_1_2)
2830
.build()
2931
}
3032

3133
@Singleton
3234
@Provides
33-
fun provideWPostDao(appDatabase: PostDatabase): PostDaoCoroutines {
34-
return appDatabase.postDao()
35-
}
35+
fun providePostDao(appDatabase: PostDatabase): PostDaoCoroutines = appDatabase.postDao()
3636

3737
@Provides
38-
fun provideWPostDaoRxJava3(appDatabase: PostDatabase): PostDaoRxJava3 {
39-
return appDatabase.postDaoRxJava()
40-
}
38+
fun providePostDaoRxJava3(appDatabase: PostDatabase): PostDaoRxJava3 =
39+
appDatabase.postDaoRxJava()
40+
41+
@Provides
42+
fun providePostStatusDao(appDatabase: PostDatabase): PostStatusDao = appDatabase.postStatusDao()
4143
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /