Added a database working in LRU (#43)
Co-authored-by: Joachim Dunant <joachim.dunant@epfl.ch>
This commit is contained in:
parent
de314dc9de
commit
2d7020fd21
|
@ -44,7 +44,7 @@ android {
|
|||
|
||||
}
|
||||
|
||||
|
||||
apply plugin: 'kotlin-kapt'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -65,6 +65,10 @@ dependencies {
|
|||
implementation "androidx.browser:browser:1.2.0"
|
||||
implementation 'com.google.android.material:material:1.1.0'
|
||||
|
||||
def room_version = "2.2.4"
|
||||
implementation "androidx.room:room-runtime:$room_version"
|
||||
kapt "androidx.room:room-compiler:$room_version"
|
||||
implementation "androidx.room:room-ktx:$room_version"
|
||||
|
||||
implementation("com.github.bumptech.glide:glide:4.11.0") {
|
||||
exclude group: "com.android.support"
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.PostDao
|
||||
import com.h.pixeldroid.db.PostEntity
|
||||
import com.h.pixeldroid.utils.*
|
||||
import org.junit.After
|
||||
import org.junit.Assert
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.Calendar
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class AppDatabaseTest {
|
||||
private var postDao: PostDao? = null
|
||||
private var db: AppDatabase? = null
|
||||
private var postTest = PostEntity(1, "test", date= Calendar.getInstance().time)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
AppDatabase.TEST_MODE = true
|
||||
db = AppDatabase.getDatabase(ApplicationProvider.getApplicationContext())
|
||||
postDao = db?.postDao()
|
||||
postDao?.insertAll(postTest)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testInsertPostItem() {
|
||||
Assert.assertEquals(postTest.domain, postDao?.getById(postTest.uid)!!.domain)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDeleteAll(){
|
||||
postDao?.deleteAll()
|
||||
Assert.assertEquals(postDao?.getPostsCount(), 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUtilsInsertAll() {
|
||||
val postTest2 = PostEntity(2, "test", date= Calendar.getInstance().time)
|
||||
DatabaseUtils.insertAllPosts(db!!, postTest, postTest2)
|
||||
|
||||
Assert.assertEquals(postTest.domain, postDao?.getById(postTest.uid)!!.domain)
|
||||
Assert.assertEquals(postTest2.domain, postDao?.getById(postTest2.uid)!!.domain)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUtilsLRU() {
|
||||
for(i in 1..db!!.MAX_NUMBER_OF_POSTS) {
|
||||
DatabaseUtils.insertAllPosts(db!!, PostEntity(i, i.toString(), date= Calendar.getInstance().time))
|
||||
}
|
||||
|
||||
Assert.assertEquals("1", postDao?.getById(1)!!.domain)
|
||||
Assert.assertEquals(db?.MAX_NUMBER_OF_POSTS, postDao?.getPostsCount())
|
||||
|
||||
DatabaseUtils.insertAllPosts(db!!, PostEntity(0, "0", date= Calendar.getInstance().time))
|
||||
Assert.assertEquals(db?.MAX_NUMBER_OF_POSTS, postDao?.getPostsCount())
|
||||
val eldestPost = postDao?.getById(1)
|
||||
Assert.assertEquals(null, eldestPost)
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
|
@ -19,6 +20,7 @@ import com.h.pixeldroid.motions.OnSwipeListener
|
|||
class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
private lateinit var drawerLayout: DrawerLayout
|
||||
private val newPostsActivityRequestCode = Activity.RESULT_OK
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
@ -69,7 +71,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
supportFragmentManager.beginTransaction().replace(R.id.fragment_container, fragment).commit()
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
When clicking in the drawer menu, go to the corresponding activity
|
||||
*/
|
||||
override fun onNavigationItemSelected(@NonNull item: MenuItem): Boolean {
|
||||
|
@ -83,7 +85,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
Launches the given activity and put it as the current one
|
||||
*/
|
||||
private fun launchActivity(activity: AppCompatActivity) {
|
||||
|
@ -91,8 +93,8 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
|
|||
startActivity(intent)
|
||||
}
|
||||
|
||||
/*
|
||||
Closes the drawer if we are clicking behind it
|
||||
/**
|
||||
Closes the drawer if it is open, when we press the back button
|
||||
*/
|
||||
override fun onBackPressed() {
|
||||
if(drawerLayout.isDrawerOpen(GravityCompat.START)){
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package com.h.pixeldroid.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
|
||||
@Database(entities = [PostEntity::class], version = 1)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun postDao(): PostDao
|
||||
val MAX_NUMBER_OF_POSTS = 100
|
||||
|
||||
companion object {
|
||||
// Singleton prevents multiple instances of database opening at the
|
||||
// same time.
|
||||
@Volatile
|
||||
private var INSTANCE: AppDatabase? = null
|
||||
var TEST_MODE = false
|
||||
|
||||
fun getDatabase(context: Context): AppDatabase {
|
||||
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
var instance: AppDatabase? = null
|
||||
|
||||
// To be able to create a temporary database that flushes when tests are over
|
||||
instance = if (TEST_MODE) {
|
||||
Room.inMemoryDatabaseBuilder(context, AppDatabase::class.java).allowMainThreadQueries().build()
|
||||
} else {
|
||||
Room.databaseBuilder(
|
||||
context.applicationContext, AppDatabase::class.java, "posts_database"
|
||||
).build()
|
||||
}
|
||||
|
||||
INSTANCE = instance
|
||||
return instance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.h.pixeldroid.db
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import java.util.Date
|
||||
|
||||
class Converters {
|
||||
@TypeConverter
|
||||
fun fromTimestamp(value: Long?): Date? {
|
||||
return value?.let { Date(it) }
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun dateToTimestamp(date: Date?): Long? {
|
||||
return date?.time?.toLong()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.h.pixeldroid.db
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy.REPLACE
|
||||
import androidx.room.Query
|
||||
import java.util.Date
|
||||
|
||||
@Dao
|
||||
interface PostDao {
|
||||
@Query("SELECT * FROM posts")
|
||||
fun getAll(): LiveData<List<PostEntity>>
|
||||
|
||||
@Query("SELECT * FROM posts WHERE uid = :postId")
|
||||
fun getById(postId: Int): PostEntity
|
||||
|
||||
@Query("SELECT count(*) FROM posts")
|
||||
fun getPostsCount(): Int
|
||||
|
||||
@Query("UPDATE posts SET date = :date WHERE uid = :postId")
|
||||
fun addDateToPost(postId: Int, date: Date)
|
||||
|
||||
@Query("DELETE FROM posts")
|
||||
fun deleteAll()
|
||||
|
||||
@Query("DELETE FROM posts WHERE date IN (SELECT min(date) FROM posts) ")
|
||||
fun deleteOldestPost(): Int
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
fun insertAll(vararg posts: PostEntity)
|
||||
|
||||
@Delete
|
||||
fun delete(post: PostEntity)
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.h.pixeldroid.db
|
||||
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.PrimaryKey;
|
||||
import java.util.Date
|
||||
|
||||
@Entity(tableName= "posts")
|
||||
data class PostEntity(
|
||||
@PrimaryKey val uid: Int,
|
||||
@ColumnInfo(name = "domain") val domain: String? = "",
|
||||
@ColumnInfo(name = "username") val username: String? = "",
|
||||
@ColumnInfo(name = "display name") val displayName: String? = "",
|
||||
@ColumnInfo(name = "accountID") val accountID: Int? = -1,
|
||||
@ColumnInfo(name = "image url") val ImageURL: String? = "",
|
||||
@ColumnInfo(name = "date") val date: Date?
|
||||
)
|
|
@ -0,0 +1,45 @@
|
|||
package com.h.pixeldroid.utils
|
||||
|
||||
import com.h.pixeldroid.db.AppDatabase
|
||||
import com.h.pixeldroid.db.PostEntity
|
||||
import java.util.Calendar
|
||||
|
||||
class DatabaseUtils {
|
||||
companion object {
|
||||
/**
|
||||
* Inserts one post into the specified database,
|
||||
* after it has checked the LRU
|
||||
*/
|
||||
fun insertPost(db: AppDatabase, post: PostEntity) {
|
||||
if (!IsInsertable(db)) {
|
||||
removeEldestPost(db)
|
||||
}
|
||||
|
||||
db.postDao().addDateToPost(post.uid, Calendar.getInstance().time)
|
||||
db.postDao().insertAll(post)
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts multiple posts into the specified database
|
||||
*/
|
||||
fun insertAllPosts(db: AppDatabase, vararg posts: PostEntity) {
|
||||
posts.forEach { insertPost(db, it) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if we can add one post into the database
|
||||
* or if it is full
|
||||
*/
|
||||
private fun IsInsertable(db: AppDatabase): Boolean {
|
||||
return db.postDao().getPostsCount() + 1 <= db.MAX_NUMBER_OF_POSTS
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the eldest post from the database
|
||||
*/
|
||||
private fun removeEldestPost(db: AppDatabase) {
|
||||
db.postDao().deleteOldestPost()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||
</vector>
|
|
@ -17,4 +17,12 @@
|
|||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
|
||||
<style name="posts_title">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_marginBottom">8dp</item>
|
||||
<item name="android:paddingLeft">8dp</item>
|
||||
<item name="android:background">@android:color/holo_orange_light</item>
|
||||
<item name="android:textAppearance">@android:style/TextAppearance.Large</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue