Skip to content

Commit 578e21a

Browse files
authored
Merge pull request #7 from msnodeve/feature/search
feat: Search 깃허브 아이디 room db 사용
2 parents 0f530ab + 244a383 commit 578e21a

9 files changed

Lines changed: 245 additions & 18 deletions

File tree

app/build.gradle

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,16 @@ android {
3838
}
3939
lintOptions {
4040
abortOnError false
41+
disable 'GradleDependency' // noinspection GradleDependency 경고 비활성화
4142
}
4243
buildToolsVersion '28.0.3'
4344
ndkVersion '20.1.5948944'
4445
}
4546

4647
dependencies {
48+
def room_version = "2.2.5"
49+
4750
implementation fileTree(dir: 'libs', include: ['*.jar'])
48-
//noinspection GradleDependency
4951
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
5052
implementation 'com.google.android.material:material:1.3.0-beta01'
5153
implementation 'androidx.appcompat:appcompat:1.2.0'
@@ -55,25 +57,26 @@ dependencies {
5557
// 머티리얼 디자인 라이브러리
5658
implementation 'com.rengwuxian.materialedittext:library:2.1.4'
5759

60+
// room
61+
implementation "androidx.room:room-runtime:$room_version"
62+
implementation "androidx.room:room-ktx:$room_version"
63+
kapt "androidx.room:room-compiler:$room_version"
64+
androidTestImplementation "androidx.room:room-testing:$room_version"
65+
5866
// test implementation
59-
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
6067
testImplementation 'junit:junit:4.12'
61-
testImplementation 'org.robolectric:robolectric:4.3'
62-
testImplementation 'org.powermock:powermock-api-mockito:1.4.12'
63-
testImplementation 'org.powermock:powermock-module-junit4:1.6.2'
64-
testImplementation 'org.mockito:mockito-core:2.28.2'
65-
testImplementation 'androidx.arch.core:core-testing:2.1.0'
6668
androidTestImplementation 'androidx.test:runner:1.2.0'
6769
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
68-
androidTestImplementation 'androidx.test:runner:1.2.0'
69-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
70-
androidTestImplementation 'androidx.test:runner:1.2.0'
7170
androidTestImplementation 'androidx.test:rules:1.2.0'
7271
androidTestImplementation 'androidx.test:core:1.2.0'
73-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
7472
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
75-
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
7673
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0'
74+
// implementation 'androidx.legacy:legacy-support-v4:1.0.0'
75+
// testImplementation 'org.robolectric:robolectric:4.3'
76+
// testImplementation 'org.powermock:powermock-api-mockito:1.4.12'
77+
// testImplementation 'org.powermock:powermock-module-junit4:1.6.2'
78+
// testImplementation 'androidx.arch.core:core-testing:2.1.0'
79+
7780

7881
// Google Ads
7982
implementation 'com.google.android.gms:play-services-ads:18.2.0'
@@ -87,15 +90,13 @@ dependencies {
8790
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
8891
implementation 'com.google.code.gson:gson:2.8.5'
8992

90-
// room
91-
implementation 'androidx.room:room-runtime:2.2.0'
92-
kapt 'androidx.room:room-compiler:2.2.0'
93-
kaptTest 'androidx.room:room-testing:2.2.0'
94-
9593
// Lifecycle components
9694
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
9795
implementation 'android.arch.lifecycle:viewmodel:1.1.1'
9896
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.1.0'
97+
implementation 'android.arch.lifecycle:extensions:1.0.0';
98+
//noinspection LifecycleAnnotationProcessorWithJava8
99+
annotationProcessor 'android.arch.lifecycle:compiler:1.0.0';
99100

100101
// Coroutines
101102
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.seok.gfd.room.dao
2+
3+
import androidx.room.Room
4+
import androidx.test.ext.junit.runners.AndroidJUnit4
5+
import androidx.test.platform.app.InstrumentationRegistry
6+
import com.seok.gfd.room.AppDatabase
7+
import com.seok.gfd.room.entity.SearchGithubId
8+
import kotlinx.coroutines.runBlocking
9+
import org.junit.After
10+
import org.junit.Before
11+
12+
import org.junit.Assert.*
13+
import org.junit.Test
14+
import org.junit.runner.RunWith
15+
16+
@RunWith(AndroidJUnit4::class)
17+
class SearchGithubIdDaoTest {
18+
private lateinit var db : AppDatabase
19+
20+
@Before
21+
fun createDb() {
22+
val context = InstrumentationRegistry.getInstrumentation().targetContext
23+
assertEquals("com.seok.gfd", context.packageName)
24+
25+
db = Room.inMemoryDatabaseBuilder(
26+
context,
27+
AppDatabase::class.java
28+
).build()
29+
}
30+
31+
@After
32+
fun closeDb() = runBlocking {
33+
db.searchGithubIdDao().deleteAll()
34+
db.close()
35+
}
36+
37+
@Test
38+
fun iWantToKnowTheDatabaseIsFind() = runBlocking{
39+
val searchGithubId = SearchGithubId(gidName = "github")
40+
41+
db.searchGithubIdDao().insert(searchGithubId)
42+
var entity = db.searchGithubIdDao().selectAll("g")[0]
43+
assertHabitEquals(searchGithubId, entity)
44+
45+
db.searchGithubIdDao().delete(entity)
46+
assertEquals(0, db.searchGithubIdDao().selectAll("g").size)
47+
}
48+
49+
private fun assertHabitEquals(expected: SearchGithubId, actual: SearchGithubId) {
50+
// id 는 자동생성되므로, 검증을 위해서 id의 동일성은 무시
51+
assertEquals(expected.copy(), actual.copy())
52+
}
53+
54+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.seok.gfd.room
2+
3+
import android.content.Context
4+
import androidx.room.Database
5+
import androidx.room.Room
6+
import androidx.room.RoomDatabase
7+
import androidx.room.TypeConverters
8+
import com.seok.gfd.room.converter.DateConverter
9+
import com.seok.gfd.room.dao.SearchGithubIdDao
10+
import com.seok.gfd.room.entity.SearchGithubId
11+
12+
@Database(entities = [SearchGithubId::class], version = 2)
13+
@TypeConverters(DateConverter::class)
14+
abstract class AppDatabase : RoomDatabase() {
15+
abstract fun searchGithubIdDao(): SearchGithubIdDao
16+
17+
companion object {
18+
private var INSTANCE: AppDatabase? = null
19+
20+
fun getInstance(context: Context): AppDatabase {
21+
if (INSTANCE == null) {
22+
synchronized(AppDatabase::class) {
23+
INSTANCE = Room.databaseBuilder(
24+
context.applicationContext,
25+
AppDatabase::class.java, "cat.db"
26+
)
27+
.fallbackToDestructiveMigration()
28+
.build()
29+
}
30+
}
31+
return INSTANCE!!
32+
}
33+
34+
fun destroyInstance(){
35+
INSTANCE = null
36+
}
37+
}
38+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.seok.gfd.room.converter
2+
3+
import androidx.room.TypeConverter
4+
import java.util.*
5+
6+
class DateConverter {
7+
@TypeConverter
8+
fun fromTimestamp(value: Long?): Date? {
9+
return value?.let { Date(it) }
10+
}
11+
12+
@TypeConverter
13+
fun dateToTimestamp(date: Date?): Long? {
14+
return date?.time?.toLong()
15+
}
16+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.seok.gfd.room.dao
2+
3+
import androidx.room.*
4+
import com.seok.gfd.room.entity.SearchGithubId
5+
6+
private const val TABLE_NAME = "search_github_ids"
7+
8+
@Dao
9+
interface SearchGithubIdDao {
10+
@Insert(onConflict = OnConflictStrategy.REPLACE)
11+
suspend fun insert(searchGithubId: SearchGithubId) : Long
12+
13+
@Delete
14+
suspend fun delete(searchGithubId: SearchGithubId)
15+
16+
@Query("SELECT * FROM $TABLE_NAME WHERE gid_name LIKE :gidName || '%' ORDER BY created DESC")
17+
suspend fun selectAll(gidName : String) : List<SearchGithubId>
18+
19+
@Query("delete from $TABLE_NAME")
20+
suspend fun deleteAll()
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.seok.gfd.room.entity
2+
3+
import androidx.room.ColumnInfo
4+
import androidx.room.Entity
5+
import androidx.room.PrimaryKey
6+
import java.util.*
7+
8+
private const val TABLE_NAME = "search_github_ids"
9+
10+
@Entity(tableName = TABLE_NAME)
11+
data class SearchGithubId(
12+
@ColumnInfo(name = "gid_name") val gidName: String?
13+
) {
14+
@PrimaryKey(autoGenerate = true)
15+
var gid: Int = 0
16+
@ColumnInfo(name = "created", defaultValue = "CURRENT_TIMESTAMP")
17+
var created: Date? = Date()
18+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.seok.gfd.viewmodel
2+
3+
import android.app.Application
4+
import androidx.lifecycle.AndroidViewModel
5+
import androidx.lifecycle.LiveData
6+
import androidx.lifecycle.MutableLiveData
7+
import androidx.room.Room
8+
import com.seok.gfd.room.AppDatabase
9+
import com.seok.gfd.room.entity.SearchGithubId
10+
import kotlinx.coroutines.runBlocking
11+
12+
class GithubIdViewModel(val context: Application) : AndroidViewModel(context){
13+
private val TAG = this.javaClass.toString()
14+
15+
private val _githubIds = MutableLiveData<List<SearchGithubId>>()
16+
17+
val githubIds : LiveData<List<SearchGithubId>>
18+
get() = _githubIds
19+
20+
fun insertGithubId(githubId: SearchGithubId){
21+
val database = AppDatabase.getInstance(context)
22+
runBlocking {
23+
database.searchGithubIdDao().insert(githubId)
24+
}
25+
}
26+
27+
fun getGithubId(name : String){
28+
val database = AppDatabase.getInstance(context)
29+
runBlocking {
30+
_githubIds.value = database.searchGithubIdDao().selectAll(name)
31+
database.close()
32+
}
33+
}
34+
}

app/src/main/java/com/seok/gfd/views/SearchActivity.kt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,43 @@
11
package com.seok.gfd.views
22

33
import android.os.Bundle
4+
import android.util.Log
45
import android.view.WindowManager
56
import android.view.animation.AnimationUtils
67
import androidx.appcompat.app.AppCompatActivity
8+
import androidx.lifecycle.Observer
9+
import androidx.lifecycle.ViewModelProviders
10+
import androidx.room.Room
711
import com.seok.gfd.R
12+
import com.seok.gfd.room.AppDatabase
13+
import com.seok.gfd.room.entity.SearchGithubId
14+
import com.seok.gfd.viewmodel.GithubIdViewModel
815
import kotlinx.android.synthetic.main.activity_search.*
16+
import kotlinx.coroutines.runBlocking
17+
import java.util.*
918

1019
class SearchActivity : AppCompatActivity() {
20+
private lateinit var githubIdsViewModel: GithubIdViewModel
21+
1122
override fun onCreate(savedInstanceState: Bundle?) {
1223
super.onCreate(savedInstanceState)
1324
setContentView(R.layout.activity_search)
1425
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
1526

27+
init()
1628
setAnimation()
1729
}
1830

31+
private fun init() {
32+
githubIdsViewModel = ViewModelProviders.of(this).get(GithubIdViewModel::class.java)
33+
githubIdsViewModel.githubIds.observe(this, Observer {
34+
for(a in it){
35+
println("data${a.gid},${a.gidName},${a.created}")
36+
}
37+
})
38+
githubIdsViewModel.getGithubId("t")
39+
}
40+
1941
private fun setAnimation() {
2042
val bottomToTop = AnimationUtils.loadAnimation(this, R.anim.bottom_to_top)
2143
search_txt_info2.startAnimation(bottomToTop)
@@ -26,4 +48,28 @@ class SearchActivity : AppCompatActivity() {
2648
leftToRight.startOffset = 800
2749
search_layout_id.startAnimation(leftToRight)
2850
}
51+
52+
// private fun iWantToKnowTheDatabaseIsFind() {
53+
// // 테스트 용으로 메모리상 생성
54+
// val database = Room.inMemoryDatabaseBuilder(
55+
// this,
56+
// AppDatabase::class.java
57+
// ).build()
58+
//
59+
// // id를 0 으로 설정해주어서 id가 autoGeneration 되게 한다.
60+
// val test = SearchGithubId(gidName = "test")
61+
// runBlocking {
62+
// // 습관을 씁니다.
63+
// database.searchGithubIdDao().insert(test)
64+
//
65+
// // 실제 DB에 써진 것을 확인합니다.
66+
// var dbHabitSchema = database.searchGithubIdDao().selectAll("t")[0]
67+
// Log.d(this.javaClass.name, "방금 넣은 것 $dbHabitSchema")
68+
//
69+
// // 지우는 것도 잘 동작하는지 확인해 봅니다.
70+
// database.searchGithubIdDao().delete(dbHabitSchema)
71+
//
72+
// Log.d(this.javaClass.name, "방금 지워서 아무것도 없음. ${database.searchGithubIdDao().selectAll("t")}")
73+
// }
74+
// }
2975
}

app/src/main/res/values/styles.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616
<style name="AppLightTheme.Button" parent="Widget.MaterialComponents.Button.OutlinedButton">
1717
<item name="strokeColor">@color/primaryGray3</item>
1818
<item name="android:textColor">@color/blue</item>
19-
<item name="strokeWidth">2dp</item>
19+
<item name="strokeWidth">1dp</item>
2020
</style>
2121
</resources>

0 commit comments

Comments
 (0)