From 39a2e304280c3563da17ac9feacf4990cc647073 Mon Sep 17 00:00:00 2001 From: Colin McNeil Date: Sun, 9 May 2021 14:03:19 -0400 Subject: [PATCH] Convert app to use Room Persistence Lib --- .idea/dictionaries/Dapper.xml | 8 +++++ app/build.gradle | 4 +++ app/src/main/java/com/xfactor/noted/Lists.kt | 33 +++++++++++-------- .../java/com/xfactor/noted/MainActivity.kt | 11 +++++-- .../com/xfactor/noted/databse/AppDatabase.kt | 10 ++++++ .../java/com/xfactor/noted/databse/List.kt | 11 +++++++ .../java/com/xfactor/noted/databse/ListDao.kt | 20 +++++++++++ .../com/xfactor/noted/databse/ListItem.kt | 11 +++++++ .../com/xfactor/noted/databse/ListItemDao.kt | 18 ++++++++++ .../noted/databse/ListWithListItems.kt | 13 ++++++++ .../noted/databse/migrations/MIGRATION_1_2.kt | 10 ++++++ .../xfactor/noted/ui/add/NewlistFragment.kt | 7 ++-- .../xfactor/noted/ui/add/NewlistViewModel.kt | 27 +++++++++------ .../noted/ui/compare/CompareFragment.kt | 4 +-- .../xfactor/noted/ui/delete/DeleteFragment.kt | 14 ++++---- .../noted/ui/delete/DeleteViewModel.kt | 13 -------- .../ui/listcontainer/ListContainerFragment.kt | 12 +++---- 17 files changed, 168 insertions(+), 58 deletions(-) create mode 100644 .idea/dictionaries/Dapper.xml create mode 100644 app/src/main/java/com/xfactor/noted/databse/AppDatabase.kt create mode 100644 app/src/main/java/com/xfactor/noted/databse/List.kt create mode 100644 app/src/main/java/com/xfactor/noted/databse/ListDao.kt create mode 100644 app/src/main/java/com/xfactor/noted/databse/ListItem.kt create mode 100644 app/src/main/java/com/xfactor/noted/databse/ListItemDao.kt create mode 100644 app/src/main/java/com/xfactor/noted/databse/ListWithListItems.kt create mode 100644 app/src/main/java/com/xfactor/noted/databse/migrations/MIGRATION_1_2.kt delete mode 100644 app/src/main/java/com/xfactor/noted/ui/delete/DeleteViewModel.kt diff --git a/.idea/dictionaries/Dapper.xml b/.idea/dictionaries/Dapper.xml new file mode 100644 index 0000000..32f12e2 --- /dev/null +++ b/.idea/dictionaries/Dapper.xml @@ -0,0 +1,8 @@ + + + + listitem + listitems + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 3555a0f..7aa3f28 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' android { compileSdkVersion 30 @@ -47,4 +48,7 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + def room_version = "2.3.0" + implementation "androidx.room:room-runtime:$room_version" + kapt "androidx.room:room-compiler:$room_version" } \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/Lists.kt b/app/src/main/java/com/xfactor/noted/Lists.kt index bcfb117..cf6f1fb 100644 --- a/app/src/main/java/com/xfactor/noted/Lists.kt +++ b/app/src/main/java/com/xfactor/noted/Lists.kt @@ -1,22 +1,29 @@ package com.xfactor.noted -data class ListItem( - val id: Long, - var title: String, - val elements: MutableList -) +import com.xfactor.noted.databse.ListItem +import com.xfactor.noted.databse.ListWithListItems -val Lists = mutableListOf( - ListItem(0, "List 1", elements = mutableListOf("Element 1", "Element 2")), - ListItem(1, "List 2", elements = mutableListOf("Element 1", "Element 2")), - ListItem(2, "List 3", elements = mutableListOf("Element 1", "Element 2")) -) +val ListsToCompare = mutableListOf() -val ListsToCompare = mutableListOf() +fun getLists() : List { + return appDatabase.listDao().getListsWithListItems() +} +fun getListItems(): List { + return appDatabase.listItemDao().getAll() +} -fun getSubItems(item: ListItem):String { - val inListForm = item.elements.mapIndexed {idx, value -> (idx+1).toString().plus(". ").plus(value)} +fun addList(list: ListWithListItems) { + appDatabase.listDao().insertAll(list.list) + appDatabase.listItemDao().insertAll(*list.ListItems.toTypedArray()) +} + +fun deleteList(list: ListWithListItems) { + appDatabase.listDao().delete(list.list) +} + +fun getSubItems(item: ListWithListItems):String { + val inListForm = item.ListItems.mapIndexed {idx, value -> (idx+1).toString().plus(". ").plus(value.value)} return inListForm.joinToString("\n") } \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/MainActivity.kt b/app/src/main/java/com/xfactor/noted/MainActivity.kt index d04184e..9726f3d 100644 --- a/app/src/main/java/com/xfactor/noted/MainActivity.kt +++ b/app/src/main/java/com/xfactor/noted/MainActivity.kt @@ -6,13 +6,21 @@ import androidx.navigation.findNavController import androidx.navigation.ui.AppBarConfiguration import androidx.navigation.ui.setupActionBarWithNavController import androidx.navigation.ui.setupWithNavController +import androidx.room.Room import com.google.android.material.bottomnavigation.BottomNavigationView +import com.xfactor.noted.databse.AppDatabase +import com.xfactor.noted.databse.migrations.MIGATION_1_2 -class MainActivity : AppCompatActivity() { +lateinit var appDatabase: AppDatabase + +class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + appDatabase = Room.databaseBuilder(applicationContext, AppDatabase::class.java, "noted-database").allowMainThreadQueries().addMigrations( + MIGATION_1_2).build() + // Setting ActionBar logo supportActionBar?.setDisplayShowHomeEnabled(true) supportActionBar?.setLogo(R.drawable.ic_logo) @@ -27,7 +35,6 @@ class MainActivity : AppCompatActivity() { R.id.navigation_delete, R.id.navigation_listcontainer, R.id.navigation_newlist)) setupActionBarWithNavController(navController, appBarConfiguration) navView.setupWithNavController(navController) - } } diff --git a/app/src/main/java/com/xfactor/noted/databse/AppDatabase.kt b/app/src/main/java/com/xfactor/noted/databse/AppDatabase.kt new file mode 100644 index 0000000..a75be69 --- /dev/null +++ b/app/src/main/java/com/xfactor/noted/databse/AppDatabase.kt @@ -0,0 +1,10 @@ +package com.xfactor.noted.databse + +import androidx.room.Database +import androidx.room.RoomDatabase + +@Database(entities = [List::class, ListItem::class], version = 2) +abstract class AppDatabase: RoomDatabase() { + abstract fun listDao(): ListDao + abstract fun listItemDao(): ListItemDao +} \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/databse/List.kt b/app/src/main/java/com/xfactor/noted/databse/List.kt new file mode 100644 index 0000000..b658718 --- /dev/null +++ b/app/src/main/java/com/xfactor/noted/databse/List.kt @@ -0,0 +1,11 @@ +package com.xfactor.noted.databse + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity +data class List ( + @PrimaryKey val uid: Int, + @ColumnInfo(name="title") val title: String +) \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/databse/ListDao.kt b/app/src/main/java/com/xfactor/noted/databse/ListDao.kt new file mode 100644 index 0000000..9522a8c --- /dev/null +++ b/app/src/main/java/com/xfactor/noted/databse/ListDao.kt @@ -0,0 +1,20 @@ +package com.xfactor.noted.databse + +import androidx.room.* +import kotlin.collections.List + +@Dao +interface ListDao { + @Query("SELECT * FROM list") + fun getAll(): List + + @Transaction + @Query("SELECT * FROM list") + fun getListsWithListItems(): List + + @Insert + fun insertAll(vararg lists: com.xfactor.noted.databse.List) + + @Delete + fun delete(list: com.xfactor.noted.databse.List) +} \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/databse/ListItem.kt b/app/src/main/java/com/xfactor/noted/databse/ListItem.kt new file mode 100644 index 0000000..4582923 --- /dev/null +++ b/app/src/main/java/com/xfactor/noted/databse/ListItem.kt @@ -0,0 +1,11 @@ +package com.xfactor.noted.databse + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity +data class ListItem ( + @PrimaryKey val uid: Int, + val listId: Int, + val value: String +) \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/databse/ListItemDao.kt b/app/src/main/java/com/xfactor/noted/databse/ListItemDao.kt new file mode 100644 index 0000000..8189c49 --- /dev/null +++ b/app/src/main/java/com/xfactor/noted/databse/ListItemDao.kt @@ -0,0 +1,18 @@ +package com.xfactor.noted.databse + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query + +@Dao +interface ListItemDao { + @Query("SELECT * FROM listitem") + fun getAll(): kotlin.collections.List + + @Insert + fun insertAll(vararg listitems: com.xfactor.noted.databse.ListItem) + + @Delete + fun delete(listitem: com.xfactor.noted.databse.ListItem) +} \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/databse/ListWithListItems.kt b/app/src/main/java/com/xfactor/noted/databse/ListWithListItems.kt new file mode 100644 index 0000000..95d1677 --- /dev/null +++ b/app/src/main/java/com/xfactor/noted/databse/ListWithListItems.kt @@ -0,0 +1,13 @@ +package com.xfactor.noted.databse + +import androidx.room.Embedded +import androidx.room.Relation + +data class ListWithListItems ( + @Embedded val list: List, + @Relation ( + parentColumn = "uid", + entityColumn = "listId" + ) + val ListItems: kotlin.collections.List +) diff --git a/app/src/main/java/com/xfactor/noted/databse/migrations/MIGRATION_1_2.kt b/app/src/main/java/com/xfactor/noted/databse/migrations/MIGRATION_1_2.kt new file mode 100644 index 0000000..026aebb --- /dev/null +++ b/app/src/main/java/com/xfactor/noted/databse/migrations/MIGRATION_1_2.kt @@ -0,0 +1,10 @@ +package com.xfactor.noted.databse.migrations + +import androidx.room.migration.Migration +import androidx.sqlite.db.SupportSQLiteDatabase + +val MIGATION_1_2 = object : Migration(1,2) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("CREATE TABLE `ListItem` (`uid` INTEGER NOT NULL, `value` TEXT NOT NULL, `listId` INTEGER NOT NULL, PRIMARY KEY(`uid`)) ") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/ui/add/NewlistFragment.kt b/app/src/main/java/com/xfactor/noted/ui/add/NewlistFragment.kt index 35fdfc2..a77795f 100644 --- a/app/src/main/java/com/xfactor/noted/ui/add/NewlistFragment.kt +++ b/app/src/main/java/com/xfactor/noted/ui/add/NewlistFragment.kt @@ -17,9 +17,8 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProviders import androidx.navigation.Navigation -import com.xfactor.noted.ListItem -import com.xfactor.noted.Lists import com.xfactor.noted.R +import com.xfactor.noted.addList import com.xfactor.noted.getSubItems class NewlistFragment : Fragment() { @@ -39,7 +38,7 @@ class NewlistFragment : Fragment() { val textView: TextView = root.findViewById(R.id.text_newlist) val elements: TextView = root.findViewById(R.id.elements_adding) newlistViewModel.listItem.observe(viewLifecycleOwner, Observer { - textView.text = it.title + textView.text = it.list.title elements.text = getSubItems(it) }) val editTitle: AppCompatEditText = root.findViewById(R.id.edit_title) @@ -68,7 +67,7 @@ class NewlistFragment : Fragment() { val submit: Button = root.findViewById(R.id.submit_newlist) submit.setOnClickListener { - Lists.add(Lists.size, newlistViewModel.listItem.value!!) + addList(newlistViewModel.listItem.value!!) Navigation.findNavController(it).navigate(R.id.navigation_listcontainer) } val cancel: Button = root.findViewById(R.id.cancel_newlist) diff --git a/app/src/main/java/com/xfactor/noted/ui/add/NewlistViewModel.kt b/app/src/main/java/com/xfactor/noted/ui/add/NewlistViewModel.kt index 586b3b5..a3f647a 100644 --- a/app/src/main/java/com/xfactor/noted/ui/add/NewlistViewModel.kt +++ b/app/src/main/java/com/xfactor/noted/ui/add/NewlistViewModel.kt @@ -4,22 +4,29 @@ import android.util.Log import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.xfactor.noted.ListItem -import com.xfactor.noted.Lists +import com.xfactor.noted.databse.ListItem +import com.xfactor.noted.databse.ListWithListItems +import com.xfactor.noted.getListItems +import com.xfactor.noted.getLists class NewlistViewModel : ViewModel() { - private var _listItem = MutableLiveData().apply { - value = ListItem(Lists.size.toLong(), "List Name", mutableListOf()) + private val lastId = getLists().last().list.uid + private val lastElementId = getListItems().last().uid + + private var _listItem = MutableLiveData().apply { + value = ListWithListItems(com.xfactor.noted.databse.List(lastId + 1, "Example title"), mutableListOf()) } - var listItem: LiveData = _listItem + var listItem: LiveData = _listItem fun setTitle(title:String) { - _listItem.postValue(ListItem(Lists.size.toLong(), title, _listItem.value!!.elements)) + _listItem.postValue(ListWithListItems(com.xfactor.noted.databse.List(_listItem.value!!.list.uid, title), _listItem.value!!.ListItems)) } fun addItem(item:String){ - Log.e("test", item) - val elements = _listItem.value!!.elements - elements.add(item) - _listItem.postValue(ListItem(Lists.size.toLong(), _listItem.value!!.title, elements)) + val currentVal = _listItem.value ?: return + val elements = currentVal.ListItems + _listItem.postValue(ListWithListItems(com.xfactor.noted.databse.List(currentVal.list.uid, currentVal.list.title), elements.plus(ListItem( + lastElementId + 1, currentVal.list.uid, item)))) + Log.e("list uid", currentVal.list.uid.toString()) + Log.e("list element uid", (getListItems().size + 1).toString()) } } \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/ui/compare/CompareFragment.kt b/app/src/main/java/com/xfactor/noted/ui/compare/CompareFragment.kt index 8704cfa..8aac81e 100644 --- a/app/src/main/java/com/xfactor/noted/ui/compare/CompareFragment.kt +++ b/app/src/main/java/com/xfactor/noted/ui/compare/CompareFragment.kt @@ -50,8 +50,8 @@ class CompareFragment : Fragment() { } val leftList = ListsToCompare[0] val rightList = ListsToCompare[1] - leftTitle.text = leftList.title - rightTitle.text = rightList.title + leftTitle.text = leftList.list.title + rightTitle.text = rightList.list.title leftTitle.paintFlags = leftTitle.paintFlags or Paint.UNDERLINE_TEXT_FLAG rightTitle.paintFlags = rightTitle.paintFlags or Paint.UNDERLINE_TEXT_FLAG leftElements.text = getSubItems(leftList) diff --git a/app/src/main/java/com/xfactor/noted/ui/delete/DeleteFragment.kt b/app/src/main/java/com/xfactor/noted/ui/delete/DeleteFragment.kt index fd223c0..6b55091 100644 --- a/app/src/main/java/com/xfactor/noted/ui/delete/DeleteFragment.kt +++ b/app/src/main/java/com/xfactor/noted/ui/delete/DeleteFragment.kt @@ -10,35 +10,33 @@ import android.widget.LinearLayout import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProviders import androidx.navigation.Navigation -import com.xfactor.noted.Lists import com.xfactor.noted.ListsToCompare import com.xfactor.noted.R +import com.xfactor.noted.deleteList +import com.xfactor.noted.getLists class DeleteFragment : Fragment() { - private lateinit var deleteViewModel: DeleteViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - deleteViewModel = - ViewModelProviders.of(this).get(DeleteViewModel::class.java) val root = inflater.inflate(R.layout.fragment_delete, container, false) val deleteButtons = root.findViewById(R.id.delete_buttons) - Lists.forEachIndexed { index, listItem -> + getLists().forEachIndexed { _, listItem -> val newButton = Button(context) - newButton.text = listItem.title + newButton.text = listItem.list.title newButton.setOnClickListener { AlertDialog.Builder(context) .setTitle("Delete List") - .setMessage("Do you really want to delete list \"".plus(listItem.title).plus("\"?")) + .setMessage("Do you really want to delete list \"".plus(listItem.list.title).plus("\"?")) .setIcon(android.R.drawable.ic_dialog_alert) .setPositiveButton("Delete") { _, _ -> - Lists.removeAt(index) + deleteList(listItem) ListsToCompare.clear() Navigation.findNavController(it).navigate(R.id.navigation_listcontainer) } diff --git a/app/src/main/java/com/xfactor/noted/ui/delete/DeleteViewModel.kt b/app/src/main/java/com/xfactor/noted/ui/delete/DeleteViewModel.kt deleted file mode 100644 index 2690311..0000000 --- a/app/src/main/java/com/xfactor/noted/ui/delete/DeleteViewModel.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.xfactor.noted.ui.delete - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel - -class DeleteViewModel : ViewModel() { - - private val _text = MutableLiveData().apply { - value = "This is delete Fragment" - } - val text: LiveData = _text -} \ No newline at end of file diff --git a/app/src/main/java/com/xfactor/noted/ui/listcontainer/ListContainerFragment.kt b/app/src/main/java/com/xfactor/noted/ui/listcontainer/ListContainerFragment.kt index bd8dc34..35f1ed7 100644 --- a/app/src/main/java/com/xfactor/noted/ui/listcontainer/ListContainerFragment.kt +++ b/app/src/main/java/com/xfactor/noted/ui/listcontainer/ListContainerFragment.kt @@ -2,7 +2,6 @@ package com.xfactor.noted.ui.listcontainer import android.graphics.Paint import android.os.Bundle -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -12,6 +11,7 @@ import androidx.fragment.app.Fragment import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView import com.xfactor.noted.* +import com.xfactor.noted.databse.ListWithListItems import kotlinx.android.synthetic.main.fragment_listcontainer.view.* import kotlinx.android.synthetic.main.fragment_listitem.view.* @@ -19,16 +19,16 @@ private lateinit var statusText : TextView; fun updateStatus() { if(ListsToCompare.size == 0) return - var status = "Selected: ".plus(ListsToCompare[0].title) + var status = "Selected: ".plus(ListsToCompare[0].list.title) if(ListsToCompare.size == 2) { - status = status.plus(", ").plus(ListsToCompare[1].title) + status = status.plus(", ").plus(ListsToCompare[1].list.title) } statusText.text = status } class ListContainerFragment : Fragment() { - private var adapter = ListsAdapter(Lists); + private var adapter = ListsAdapter(getLists()); override fun onCreateView( inflater: LayoutInflater, @@ -44,7 +44,7 @@ class ListContainerFragment : Fragment() { } } -class ListsAdapter(private val dataSet: MutableList) : +class ListsAdapter(private val dataSet: List) : RecyclerView.Adapter() { class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { @@ -60,7 +60,7 @@ class ListsAdapter(private val dataSet: MutableList) : updateStatus() } val title = viewHolder.listItem.list_title - title.text = dataSet[position].title + title.text = dataSet[position].list.title title.paintFlags = title.paintFlags or Paint.UNDERLINE_TEXT_FLAG viewHolder.listItem.list_elements.text = getSubItems(dataSet[position]) val visibility: Int = viewHolder.listItem.visibility