Skip to content

Commit

Permalink
improve data cache
Browse files Browse the repository at this point in the history
  • Loading branch information
Razeeman committed Oct 20, 2024
1 parent ea032c4 commit 15eb62d
Show file tree
Hide file tree
Showing 19 changed files with 215 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class RecordRepoImpl @Inject constructor(

private var getFromRangeCache = LruCache<GetFromRangeKey, List<Record>>(10)
private var getFromRangeByTypeCache = LruCache<GetFromRangeByTypeKey, List<Record>>(1)
private var recordCache = LruCache<Long, Record>(1)
private var isEmpty: Boolean? = null
private val mutex: Mutex = Mutex()

Expand Down Expand Up @@ -68,10 +69,12 @@ class RecordRepoImpl @Inject constructor(
recordDao.searchAnyComments().map(::mapItem)
}

override suspend fun get(id: Long): Record? = withContext(Dispatchers.IO) {
logDataAccess("get")
recordDao.get(id)?.let(::mapItem)
}
override suspend fun get(id: Long): Record? = mutex.withLockedCache(
logMessage = "get",
accessCache = { recordCache[id] },
accessSource = { recordDao.get(id)?.let(::mapItem) },
afterSourceAccess = { it?.let { recordCache.put(id, it) } }
)

override suspend fun getFromRange(range: Range): List<Record> {
val cacheKey = GetFromRangeKey(range)
Expand All @@ -92,7 +95,7 @@ class RecordRepoImpl @Inject constructor(
val cacheKey = GetFromRangeByTypeKey(typeIds, range)
return mutex.withLockedCache(
logMessage = "getFromRangeByType",
accessCache = { getFromRangeByTypeCache.get(cacheKey) },
accessCache = { getFromRangeByTypeCache[cacheKey] },
accessSource = {
recordDao.getFromRangeByType(
typesIds = typeIds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.example.util.simpletimetracker.data_local.repo

import com.example.util.simpletimetracker.data_local.database.RunningRecordDao
import com.example.util.simpletimetracker.data_local.mapper.RunningRecordDataLocalMapper
import com.example.util.simpletimetracker.data_local.utils.logDataAccess
import com.example.util.simpletimetracker.data_local.utils.removeIf
import com.example.util.simpletimetracker.data_local.utils.replaceWith
import com.example.util.simpletimetracker.data_local.utils.withLockedCache
Expand Down Expand Up @@ -39,6 +40,13 @@ class RunningRecordRepoImpl @Inject constructor(
accessSource = { dao.get(id)?.let(mapper::map) },
)

override suspend fun has(id: Long): Boolean = mutex.withLockedCache(
logMessage = "has",
accessCache = { cache?.any { it.id == id } },
accessSource = { dao.get(id) != null },
afterSourceAccess = { initializeCache() }
)

override suspend fun add(runningRecord: RunningRecord): Long = mutex.withLockedCache(
logMessage = "add",
accessSource = { dao.insert(runningRecord.let(mapper::map)) },
Expand All @@ -58,4 +66,9 @@ class RunningRecordRepoImpl @Inject constructor(
accessSource = { dao.clear() },
afterSourceAccess = { cache = null },
)

private suspend fun initializeCache() {
logDataAccess("initializeCache")
cache = dao.getAll().map(mapper::map)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ class RunningRecordInteractor @Inject constructor(
return runningRecordRepo.get(id)
}

suspend fun has(id: Long): Boolean {
return runningRecordRepo.has(id)
}

suspend fun add(runningRecord: RunningRecord) {
val recordId = runningRecordRepo.add(runningRecord)
runningRecordToRecordTagRepo.removeAllByRunningRecordId(recordId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import com.example.util.simpletimetracker.domain.model.WidgetType

interface WidgetInteractor {

fun initializeCachedViews()

fun updateSingleWidget(widgetId: Int)

fun updateSingleWidgets(typeIds: List<Long>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ interface RunningRecordRepo {

suspend fun get(id: Long): RunningRecord?

suspend fun has(id: Long): Boolean

suspend fun add(runningRecord: RunningRecord): Long

suspend fun remove(id: Long)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class ChangeRecordFragment :
private val core by lazy { ChangeRecordCore(viewModel = viewModel) }

private val extra: ChangeRecordParams by fragmentArgumentDelegate(
key = ARGS_PARAMS, default = ChangeRecordParams.New(),
key = ARGS_PARAMS, default = ChangeRecordParams.New(0),
)

override fun initUi(): Unit = with(binding) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.example.util.simpletimetracker.domain.interactor.RecordInteractor
import com.example.util.simpletimetracker.domain.interactor.RecordTypeToTagInteractor
import com.example.util.simpletimetracker.domain.interactor.UpdateExternalViewsInteractor
import com.example.util.simpletimetracker.domain.model.ChartFilterType
import com.example.util.simpletimetracker.domain.model.DayOfWeek
import com.example.util.simpletimetracker.domain.model.RangeLength
import com.example.util.simpletimetracker.domain.model.Record
import com.example.util.simpletimetracker.feature_change_record.interactor.ChangeRecordViewDataInteractor
Expand All @@ -35,11 +36,11 @@ import javax.inject.Inject
class ChangeRecordViewModel @Inject constructor(
recordTypesViewDataInteractor: RecordTypesViewDataInteractor,
recordTagViewDataInteractor: RecordTagViewDataInteractor,
prefsInteractor: PrefsInteractor,
snackBarMessageNavigationInteractor: SnackBarMessageNavigationInteractor,
changeRecordActionsDelegate: ChangeRecordActionsDelegateImpl,
recordTypeToTagInteractor: RecordTypeToTagInteractor,
favouriteCommentInteractor: FavouriteCommentInteractor,
private val prefsInteractor: PrefsInteractor,
private val router: Router,
private val recordInteractor: RecordInteractor,
private val addRecordMediator: AddRecordMediator,
Expand Down Expand Up @@ -134,6 +135,7 @@ class ChangeRecordViewModel @Inject constructor(
if (newTypeId != originalTypeId) {
externalViewsInteractor.onRecordChangeType(originalTypeId)
}
warmupCache(extra.daysFromToday)
router.back()
}
}
Expand All @@ -154,6 +156,17 @@ class ChangeRecordViewModel @Inject constructor(
super.onTimeStartedChanged()
}

private suspend fun warmupCache(actualShift: Int) {
if (prefsInteractor.getShowRecordsCalendar()) return
val range = timeMapper.getRangeStartAndEnd(
rangeLength = RangeLength.Day,
shift = actualShift,
firstDayOfWeek = DayOfWeek.MONDAY, // Doesn't matter for days.
startOfDayShift = prefsInteractor.getStartOfDayShift(),
)
recordInteractor.getFromRange(range)
}

private fun getInitialTimeEnded(daysFromToday: Int): Long {
return timeMapper.toTimestampShifted(daysFromToday, RangeLength.Day)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ChangeRunningRecordFragment :
private val core by lazy { ChangeRecordCore(viewModel = viewModel) }

private val params: ChangeRunningRecordParams by fragmentArgumentDelegate(
key = ARGS_PARAMS, default = ChangeRunningRecordParams(),
key = ARGS_PARAMS, default = ChangeRunningRecordParams.Empty,
)

override fun initUi(): Unit = with(binding) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.example.util.simpletimetracker.core.utils.InsetConfiguration
import com.example.util.simpletimetracker.core.utils.SHORTCUT_NAVIGATION_KEY
import com.example.util.simpletimetracker.core.view.SafeFragmentStateAdapter
import com.example.util.simpletimetracker.domain.extension.orZero
import com.example.util.simpletimetracker.domain.interactor.WidgetInteractor
import com.example.util.simpletimetracker.feature_main.R
import com.example.util.simpletimetracker.feature_main.adapter.MainContentAdapter
import com.example.util.simpletimetracker.feature_main.provider.MainTabsProvider
Expand All @@ -46,6 +47,9 @@ class MainFragment : BaseFragment<Binding>() {
@Inject
lateinit var mainTabsProvider: MainTabsProvider

@Inject
lateinit var widgetInteractor: WidgetInteractor

private val viewModel: MainViewModel by viewModels()
private val mainTabsViewModel: MainTabsViewModel by activityViewModels(
factoryProducer = { mainTabsViewModelFactory },
Expand All @@ -62,6 +66,7 @@ class MainFragment : BaseFragment<Binding>() {
override fun initUi() {
setupPager()
checkForShortcutNavigation()
widgetInteractor.initializeCachedViews()
}

override fun initUx() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,14 @@ class RecordsViewModel @Inject constructor(
transitionName = sharedElements?.second.orEmpty(),
id = item.id,
from = ChangeRecordParams.From.Records,
daysFromToday = shift,
preview = preview,
)
is RecordViewData.Untracked -> ChangeRecordParams.Untracked(
transitionName = sharedElements?.second.orEmpty(),
timeStarted = item.timeStartedTimestamp,
timeEnded = item.timeEndedTimestamp,
daysFromToday = shift,
preview = preview,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,14 @@ class RecordsAllViewModel @Inject constructor(
transitionName = sharedElements.second,
id = item.id,
from = ChangeRecordParams.From.RecordsAll,
daysFromToday = 0,
preview = preview,
)
is RecordViewData.Untracked -> ChangeRecordParams.Untracked(
transitionName = sharedElements.second,
timeStarted = item.timeStartedTimestamp,
timeEnded = item.timeEndedTimestamp,
daysFromToday = 0,
preview = preview,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import javax.inject.Inject

class WidgetInteractorImpl @Inject constructor(
private val widgetManager: WidgetManager,
private val widgetViewsHolder: WidgetViewsHolder,
) : WidgetInteractor {

override fun initializeCachedViews() = widgetViewsHolder.initialize()

override fun updateSingleWidget(widgetId: Int) = widgetManager.updateSingleWidget(widgetId)

override fun updateSingleWidgets(typeIds: List<Long>) = widgetManager.updateSingleWidgets(typeIds)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.example.util.simpletimetracker.feature_widget.interactor

import android.content.Context
import android.view.ContextThemeWrapper
import com.example.util.simpletimetracker.core.extension.allowVmViolations
import com.example.util.simpletimetracker.feature_views.IconView
import com.example.util.simpletimetracker.feature_views.RecordTypeView
import com.example.util.simpletimetracker.feature_widget.R
import com.example.util.simpletimetracker.feature_widget.statistics.customView.WidgetStatisticsChartView
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import javax.inject.Singleton

/**
* Used inflate on app start views that would be used for widgets.
*/
@Singleton
class WidgetViewsHolder @Inject constructor(
@ApplicationContext private val context: Context
) {

private var recordTypeView: RecordTypeView? = null
private var statisticsView: WidgetStatisticsChartView? = null
private var statisticsRefreshView: IconView? = null

fun initialize() {
getRecordTypeView(context)
getStatisticsView(context)
getStatisticsRefreshView(context)
}

fun getRecordTypeView(context: Context): RecordTypeView {
recordTypeView?.let { return it }
val view = allowVmViolations {
RecordTypeView(ContextThemeWrapper(context, R.style.AppTheme))
}
recordTypeView = view
return view
}

fun getStatisticsView(context: Context): WidgetStatisticsChartView {
statisticsView?.let { return it }
val view = allowVmViolations {
WidgetStatisticsChartView(ContextThemeWrapper(context, R.style.AppTheme))
}
statisticsView = view
return view
}

fun getStatisticsRefreshView(context: Context): IconView {
statisticsRefreshView?.let { return it }
val view = allowVmViolations {
IconView(ContextThemeWrapper(context, R.style.AppTheme))
}
statisticsRefreshView = view
return view
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.RemoteViews
import com.example.util.simpletimetracker.core.extension.allowDiskRead
import com.example.util.simpletimetracker.core.extension.allowVmViolations
import com.example.util.simpletimetracker.core.repo.ResourceRepo
import com.example.util.simpletimetracker.core.utils.PendingIntents
Expand Down Expand Up @@ -57,8 +58,9 @@ class WidgetQuickSettingsProvider : AppWidgetProvider() {
}
}

@OptIn(DelicateCoroutinesApi::class)
override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
GlobalScope.launch(Dispatchers.Main) {
GlobalScope.launch(allowDiskRead { Dispatchers.Main }) {
appWidgetIds?.forEach { prefsInteractor.removeQuickSettingsWidget(it) }
}
}
Expand All @@ -71,7 +73,7 @@ class WidgetQuickSettingsProvider : AppWidgetProvider() {
) {
if (context == null || appWidgetManager == null) return

GlobalScope.launch(Dispatchers.Main) {
GlobalScope.launch(allowDiskRead { Dispatchers.Main }) {
val backgroundTransparency = prefsInteractor.getWidgetBackgroundTransparencyPercent()
val name: String
val isChecked: Boolean
Expand Down Expand Up @@ -154,10 +156,11 @@ class WidgetQuickSettingsProvider : AppWidgetProvider() {
view.measureExactly(width = width, height = height)
}

@OptIn(DelicateCoroutinesApi::class)
private fun onClick(
widgetId: Int,
) {
GlobalScope.launch(Dispatchers.Main) {
GlobalScope.launch(allowDiskRead { Dispatchers.Main }) {
when (prefsInteractor.getQuickSettingsWidget(widgetId)) {
is QuickSettingsWidgetType.AllowMultitasking -> {
val newValue = !prefsInteractor.getAllowMultitasking()
Expand Down
Loading

0 comments on commit 15eb62d

Please sign in to comment.