Archived
Added database persistence ability
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'org.jetbrains.kotlin.android'
|
||||
id 'kotlin-kapt'
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -47,4 +48,7 @@ dependencies {
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||
|
||||
implementation "androidx.room:room-runtime:2.5.1"
|
||||
kapt "androidx.room:room-compiler:2.5.1"
|
||||
}
|
||||
@@ -11,7 +11,9 @@ import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.denizk0461.studip.R
|
||||
import com.denizk0461.studip.data.Dependencies
|
||||
import com.denizk0461.studip.databinding.ActivityMainBinding
|
||||
import com.denizk0461.studip.db.EventRepository
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
@@ -22,9 +24,12 @@ class MainActivity : AppCompatActivity() {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
Dependencies.repo = EventRepository(application)
|
||||
|
||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
|
||||
setSupportActionBar(binding.toolbar)
|
||||
|
||||
val navController = findNavController(R.id.nav_host_fragment_content_main)
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package com.denizk0461.studip.adapter
|
||||
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.denizk0461.studip.data.StudIPEvent
|
||||
import com.denizk0461.studip.databinding.ItemEventBinding
|
||||
import com.denizk0461.studip.databinding.ItemEventPageBinding
|
||||
|
||||
class StudIPEventAdapter(private val events: List<StudIPEvent>) : RecyclerView.Adapter<StudIPEventAdapter.EventViewHolder>() {
|
||||
|
||||
@@ -24,24 +22,13 @@ class StudIPEventAdapter(private val events: List<StudIPEvent>) : RecyclerView.A
|
||||
|
||||
override fun onBindViewHolder(holder: EventViewHolder, position: Int) {
|
||||
val currentItem = events[position]
|
||||
// var itemCount = 0
|
||||
// events.filter { it.day == position }.forEach { event ->
|
||||
// val newView = ItemEventBinding.inflate(
|
||||
// LayoutInflater.from(holder.binding.root.context),
|
||||
// holder.binding.root,
|
||||
// false
|
||||
// ).also { item ->
|
||||
// Log.d("HELLO", "generating ${event.title}...2")
|
||||
// itemCount += 1
|
||||
|
||||
holder.binding.textTitle.text = currentItem.title
|
||||
holder.binding.textLecturers.text = currentItem.lecturer.joinToString(", ")
|
||||
holder.binding.textLecturers.text = currentItem.lecturer
|
||||
holder.binding.textRoom.text = currentItem.room
|
||||
holder.binding.textTimeslot.text = currentItem.timeslot
|
||||
// }
|
||||
// holder.binding.pageLayout.addView(newView.root)
|
||||
// }
|
||||
// if (itemCount == 0) {
|
||||
// // TODO inflate view saying "no events!" or sth
|
||||
// }
|
||||
|
||||
// TODO inflate view saying "no events!" or sth
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
package com.denizk0461.studip.adapter
|
||||
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.denizk0461.studip.data.StudIPEvent
|
||||
import com.denizk0461.studip.databinding.ItemEventBinding
|
||||
import com.denizk0461.studip.databinding.ItemEventPageBinding
|
||||
|
||||
class StudIPEventPageAdapter(private val events: List<StudIPEvent>) : RecyclerView.Adapter<StudIPEventPageAdapter.EventPageViewHolder>() {
|
||||
@@ -29,26 +26,7 @@ class StudIPEventPageAdapter(private val events: List<StudIPEvent>) : RecyclerVi
|
||||
holder.binding.pageRecyclerView.apply {
|
||||
layoutManager = LinearLayoutManager(holder.binding.root.context, LinearLayoutManager.VERTICAL, false)
|
||||
adapter = StudIPEventAdapter(events.filter { it.day == position }) // TODO check if empty
|
||||
scheduleLayoutAnimation()
|
||||
}
|
||||
|
||||
// var itemCount = 0
|
||||
// events.filter { it.day == position }.forEach { event ->
|
||||
// val newView = ItemEventBinding.inflate(
|
||||
// LayoutInflater.from(holder.binding.root.context),
|
||||
// holder.binding.root,
|
||||
// false
|
||||
// ).also { item ->
|
||||
// Log.d("HELLO", "generating ${event.title}...2")
|
||||
// itemCount += 1
|
||||
// item.textTitle.text = event.title
|
||||
// item.textLecturers.text = event.lecturer.joinToString(", ")
|
||||
// item.textRoom.text = event.room
|
||||
// item.textTimeslot.text = event.timeslot
|
||||
// }
|
||||
// holder.binding.pageLayout.addView(newView.root)
|
||||
// }
|
||||
// if (itemCount == 0) {
|
||||
// // TODO inflate view saying "no events!" or sth
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.denizk0461.studip.data
|
||||
|
||||
import com.denizk0461.studip.db.EventRepository
|
||||
|
||||
object Dependencies {
|
||||
lateinit var repo: EventRepository
|
||||
}
|
||||
@@ -3,12 +3,12 @@ package com.denizk0461.studip.data
|
||||
object DummyData {
|
||||
|
||||
val events: Array<StudIPEvent> = arrayOf(
|
||||
StudIPEvent("Literatures", arrayOf("Nittel"), "MZH 1380/1400", 0, 3, 1),
|
||||
StudIPEvent("Linguistics", arrayOf("Du Bois"), "SFG 1020", 1, 1, 1),
|
||||
StudIPEvent("System Erde", arrayOf("Zolitschka", "Labuhn-Deroubaix"), "GW2 B1410", 1, 3, 1),
|
||||
StudIPEvent("Key Moments", arrayOf("Esders-Angermund"), "GW2 B2890", 2, 2, 1),
|
||||
StudIPEvent("ULS-1", arrayOf("Herrmann"), "GW2 B2890", 2, 3, 1),
|
||||
StudIPEvent("Gesellschaft und Raum", arrayOf("Lossau", "Mossig"), "GW2 B1820", 3, 1, 1),
|
||||
StudIPEvent("Gesellschaft und Raum2", arrayOf("Lossau", "Mossig"), "GW2 B1820", 4, 4, 2),
|
||||
StudIPEvent(1, "Literatures", "Nittel", "MZH 1380/1400", 0, 3, 1),
|
||||
StudIPEvent(2, "Linguistics", "Du Bois", "SFG 1020", 1, 1, 1),
|
||||
StudIPEvent(3, "System Erde", "Zolitschka, Labuhn-Deroubaix", "GW2 B1410", 1, 3, 1),
|
||||
StudIPEvent(4, "Key Moments", "Esders-Angermund", "GW2 B2890", 2, 2, 1),
|
||||
StudIPEvent(5, "ULS-1", "Herrmann", "GW2 B2890", 2, 3, 1),
|
||||
StudIPEvent(6, "Gesellschaft und Raum", "Lossau, Mossig", "GW2 B1820", 3, 1, 1),
|
||||
StudIPEvent(7, "Gesellschaft und Raum2", "Lossau, Mossig", "GW2 B1820", 4, 4, 2),
|
||||
)
|
||||
}
|
||||
@@ -1,18 +1,24 @@
|
||||
package com.denizk0461.studip.data
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@Entity(tableName = "events")
|
||||
data class StudIPEvent(
|
||||
@PrimaryKey val id: Int,
|
||||
val title: String, // the name of the event
|
||||
val lecturer: Array<String>, // the lecturer(s)
|
||||
val room: String, // the room the event takes place in; assumes that the room doesn't change
|
||||
val lecturer: String, // the lecturer(s)
|
||||
val room: String, // the room the event takes place in
|
||||
val day: Int, // 0 = Monday, 1 = Tuesday, 2 = Wednesday, 3 = Thursday, 4 = Friday
|
||||
val timeslotStart: Int, // 0 = 08:15, 1 = 10:15, 2 = 12:15, 3 = 14:15, 4 = 16:15, 5 = 18:15
|
||||
val timeslots: Int, // the amount of timeslots the course takes place over (1 timeslot = 90min)
|
||||
) {
|
||||
|
||||
private val timeSlotStartTimes: List<String> = listOf("08:15", "10:15", "12:15", "14:15", "16:15", "18:15")
|
||||
private val timeSlotEndTimes: List<String> = listOf("09:45", "11:45", "13:45", "15:45", "17:45", "19:45")
|
||||
@Ignore private val timeSlotStartTimes: List<String> = listOf("08:15", "10:15", "12:15", "14:15", "16:15", "18:15")
|
||||
@Ignore private val timeSlotEndTimes: List<String> = listOf("09:45", "11:45", "13:45", "15:45", "17:45", "19:45")
|
||||
|
||||
val timeslot: String =
|
||||
@Ignore val timeslot: String =
|
||||
"${timeSlotStartTimes[timeslotStart]} – ${timeSlotEndTimes[timeslotStart + timeslots - 1]}"
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
@@ -26,9 +32,18 @@ data class StudIPEvent(
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = title.hashCode()
|
||||
result = 31 * result + lecturer.contentHashCode()
|
||||
var result = id
|
||||
result = 31 * result + title.hashCode()
|
||||
result = 31 * result + lecturer.hashCode()
|
||||
result = 31 * result + room.hashCode()
|
||||
result = 31 * result + day
|
||||
result = 31 * result + timeslotStart
|
||||
result = 31 * result + timeslots
|
||||
result = 31 * result + timeSlotStartTimes.hashCode()
|
||||
result = 31 * result + timeSlotEndTimes.hashCode()
|
||||
result = 31 * result + timeslot.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.denizk0461.studip.db
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import com.denizk0461.studip.data.StudIPEvent
|
||||
|
||||
@Dao
|
||||
interface EventDAO {
|
||||
|
||||
@get:Query("SELECT * FROM events ORDER BY id")
|
||||
val allEvents: LiveData<List<StudIPEvent>>
|
||||
|
||||
@Insert
|
||||
fun insertEvent(event: StudIPEvent)
|
||||
|
||||
@Query("DELETE FROM events")
|
||||
fun nukeEvents()
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.denizk0461.studip.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import com.denizk0461.studip.data.StudIPEvent
|
||||
|
||||
@Database(entities = [StudIPEvent::class], version = 1)
|
||||
abstract class EventDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun dao(): EventDAO
|
||||
|
||||
companion object {
|
||||
private var instance: EventDatabase? = null
|
||||
|
||||
fun getInstance(context: Context): EventDatabase {
|
||||
if (instance == null) {
|
||||
synchronized(EventDatabase::class) {
|
||||
instance = Room.databaseBuilder(
|
||||
context.applicationContext,
|
||||
EventDatabase::class.java,
|
||||
"event_db"
|
||||
).build()
|
||||
}
|
||||
}
|
||||
return instance!!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.denizk0461.studip.db
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.denizk0461.studip.data.StudIPEvent
|
||||
|
||||
class EventRepository(app: Application) {
|
||||
|
||||
private val dao: EventDAO = EventDatabase.getInstance(app.applicationContext).dao()
|
||||
|
||||
val allEvents: LiveData<List<StudIPEvent>> = dao.allEvents
|
||||
|
||||
fun nukeEvents() { dao.nukeEvents() }
|
||||
fun insertEvent(event: StudIPEvent) { dao.insertEvent(event) }
|
||||
}
|
||||
+19
-10
@@ -5,18 +5,21 @@ import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.PagerSnapHelper
|
||||
import com.denizk0461.studip.adapter.StudIPEventPageAdapter
|
||||
import com.denizk0461.studip.data.DummyData
|
||||
import com.denizk0461.studip.databinding.FragmentFirstBinding
|
||||
import com.denizk0461.studip.databinding.FragmentEventBinding
|
||||
import com.denizk0461.studip.viewmodel.EventViewModel
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the default destination in the navigation.
|
||||
*/
|
||||
class FirstFragment : Fragment() {
|
||||
class EventFragment : Fragment() {
|
||||
|
||||
private var _binding: FragmentFirstBinding? = null
|
||||
private var _binding: FragmentEventBinding? = null
|
||||
|
||||
// This property is only valid between onCreateView and
|
||||
// onDestroyView.
|
||||
@@ -24,19 +27,25 @@ class FirstFragment : Fragment() {
|
||||
private lateinit var recyclerViewAdapter: StudIPEventPageAdapter
|
||||
private lateinit var recyclerViewLayoutManager: LinearLayoutManager
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
_binding = FragmentFirstBinding.inflate(inflater, container, false)
|
||||
private val viewModel: EventViewModel by viewModels()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
_binding = FragmentEventBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
recyclerViewAdapter = StudIPEventPageAdapter(DummyData.events.toList())
|
||||
binding.recyclerView.adapter = recyclerViewAdapter
|
||||
recyclerViewLayoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
binding.recyclerView.layoutManager = recyclerViewLayoutManager
|
||||
PagerSnapHelper().attachToRecyclerView(binding.recyclerView)
|
||||
viewModel.allEvents.observe(viewLifecycleOwner) { events ->
|
||||
recyclerViewAdapter = StudIPEventPageAdapter(DummyData.events.toList())
|
||||
binding.recyclerView.adapter = recyclerViewAdapter
|
||||
recyclerViewLayoutManager =
|
||||
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
|
||||
binding.recyclerView.layoutManager = recyclerViewLayoutManager
|
||||
PagerSnapHelper().attachToRecyclerView(binding.recyclerView)
|
||||
binding.recyclerView.scheduleLayoutAnimation()
|
||||
}
|
||||
|
||||
// binding.buttonFirst.setOnClickListener {
|
||||
// findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.denizk0461.studip.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.denizk0461.studip.data.StudIPEvent
|
||||
|
||||
class EventViewModel(app: Application) : TemplateViewModel(app) {
|
||||
|
||||
val allEvents: LiveData<List<StudIPEvent>> = repo.allEvents
|
||||
|
||||
fun insertEvent(event: StudIPEvent) { repo.insertEvent(event) }
|
||||
fun nukeEvents() { repo.nukeEvents() }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.denizk0461.studip.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.denizk0461.studip.data.Dependencies
|
||||
import com.denizk0461.studip.db.EventRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
open class TemplateViewModel(app: Application) : AndroidViewModel(app) {
|
||||
|
||||
protected val repo: EventRepository = Dependencies.repo
|
||||
|
||||
fun doAsync(function: () -> Unit) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
function()
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> returnBlocking(function: () -> T): T = runBlocking(Dispatchers.IO) {
|
||||
function()
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".fragment.FirstFragment">
|
||||
tools:context=".fragment.EventFragment">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
<fragment
|
||||
android:id="@+id/FirstFragment"
|
||||
android:name="com.denizk0461.studip.fragment.FirstFragment"
|
||||
android:name="com.denizk0461.studip.fragment.EventFragment"
|
||||
android:label="@string/first_fragment_label"
|
||||
tools:layout="@layout/fragment_first">
|
||||
tools:layout="@layout/fragment_event">
|
||||
|
||||
<action
|
||||
android:id="@+id/action_FirstFragment_to_SecondFragment"
|
||||
|
||||
Reference in New Issue
Block a user