Skip to content

Commit 8f2454e

Browse files
author
Igor Zakharov
committed
initial commit
0 parents  commit 8f2454e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1560
-0
lines changed

.gitignore

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# Created by https://www.toptal.com/developers/gitignore/api/android,androidstudio
2+
# Edit at https://www.toptal.com/developers/gitignore?templates=android,androidstudio
3+
4+
### Android ###
5+
# Gradle files
6+
.gradle/
7+
build/
8+
9+
# Local configuration file (sdk path, etc)
10+
local.properties
11+
12+
# Log/OS Files
13+
*.log
14+
15+
# Android Studio generated files and folders
16+
captures/
17+
.externalNativeBuild/
18+
.cxx/
19+
*.apk
20+
output.json
21+
22+
# IntelliJ
23+
*.iml
24+
.idea/
25+
misc.xml
26+
deploymentTargetDropDown.xml
27+
render.experimental.xml
28+
29+
# Keystore files
30+
*.jks
31+
*.keystore
32+
33+
# Android Profiling
34+
*.hprof
35+
36+
### Android Patch ###
37+
gen-external-apklibs
38+
39+
# Replacement of .externalNativeBuild directories introduced
40+
# with Android Studio 3.5.
41+
42+
### AndroidStudio ###
43+
# Covers files to be ignored for android development using Android Studio.
44+
45+
# Built application files
46+
*.ap_
47+
*.aab
48+
49+
# Files for the ART/Dalvik VM
50+
*.dex
51+
52+
# Java class files
53+
*.class
54+
55+
# Generated files
56+
bin/
57+
gen/
58+
out/
59+
60+
# Gradle files
61+
.gradle
62+
63+
# Signing files
64+
.signing/
65+
66+
# Local configuration file (sdk path, etc)
67+
68+
# Proguard folder generated by Eclipse
69+
proguard/
70+
71+
# Log Files
72+
73+
# Android Studio
74+
/*/build/
75+
/*/local.properties
76+
/*/out
77+
/*/*/build
78+
/*/*/production
79+
.navigation/
80+
*.ipr
81+
*~
82+
*.swp
83+
84+
# Keystore files
85+
86+
# Google Services (e.g. APIs or Firebase)
87+
# google-services.json
88+
89+
# Android Patch
90+
91+
# External native build folder generated in Android Studio 2.2 and later
92+
.externalNativeBuild
93+
94+
# NDK
95+
obj/
96+
97+
# IntelliJ IDEA
98+
*.iws
99+
/out/
100+
101+
# User-specific configurations
102+
.idea/caches/
103+
.idea/libraries/
104+
.idea/shelf/
105+
.idea/workspace.xml
106+
.idea/tasks.xml
107+
.idea/.name
108+
.idea/compiler.xml
109+
.idea/copyright/profiles_settings.xml
110+
.idea/encodings.xml
111+
.idea/misc.xml
112+
.idea/modules.xml
113+
.idea/scopes/scope_settings.xml
114+
.idea/dictionaries
115+
.idea/vcs.xml
116+
.idea/jsLibraryMappings.xml
117+
.idea/datasources.xml
118+
.idea/dataSources.ids
119+
.idea/sqlDataSources.xml
120+
.idea/dynamic.xml
121+
.idea/uiDesigner.xml
122+
.idea/assetWizardSettings.xml
123+
.idea/gradle.xml
124+
.idea/jarRepositories.xml
125+
.idea/navEditor.xml
126+
127+
# Legacy Eclipse project files
128+
.classpath
129+
.project
130+
.cproject
131+
.settings/
132+
133+
# Mobile Tools for Java (J2ME)
134+
.mtj.tmp/
135+
136+
# Package Files #
137+
*.war
138+
*.ear
139+
140+
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
141+
hs_err_pid*
142+
143+
## Plugin-specific files:
144+
145+
# mpeltonen/sbt-idea plugin
146+
.idea_modules/
147+
148+
# JIRA plugin
149+
atlassian-ide-plugin.xml
150+
151+
# Mongo Explorer plugin
152+
.idea/mongoSettings.xml
153+
154+
# Crashlytics plugin (for Android Studio and IntelliJ)
155+
com_crashlytics_export_strings.xml
156+
crashlytics.properties
157+
crashlytics-build.properties
158+
fabric.properties
159+
160+
### AndroidStudio Patch ###
161+
162+
!/gradle/wrapper/gradle-wrapper.jar
163+
164+
# End of https://www.toptal.com/developers/gitignore/api/android,androidstudio
165+
/.fleet
166+
/app/prod

README.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# CachedFlow
2+
3+
**A lightweight Kotlin Multiplatform caching library** designed to work using a key-based strategy system and flexible caching policies.
4+
5+
---
6+
7+
## Features
8+
9+
- Simple key-based cache access using typed keys
10+
- Customizable caching strategies
11+
- Supports suspending and flow-based data operations
12+
- Pluggable storage backend (`Store`) for full platform flexibility
13+
- Built-in logging interface
14+
- Fully testable and decoupled from Android dependencies
15+
16+
---
17+
18+
## Installation
19+
20+
> Add the library to your Kotlin Multiplatform project (available soon via Maven Central / GitHub Packages).
21+
22+
<details>
23+
<summary>Gradle (Kotlin DSL)</summary>
24+
25+
```kotlin
26+
dependencies {
27+
implementation("com.dapadz:cachedflow:<version>")
28+
}
29+
```
30+
31+
</details>
32+
33+
---
34+
35+
## Getting Started
36+
37+
### 1. Create your own `Store` implementation
38+
39+
The `Store` interface abstracts the storage layer:
40+
41+
```kotlin
42+
interface Store {
43+
suspend fun <T: Any> get(key: StoreKey<T>): Flow<T?>
44+
suspend fun <T: Any> save(key: StoreKey<T>, value: T)
45+
suspend fun <T: Any> delete(key: StoreKey<T>)
46+
suspend fun clear()
47+
}
48+
```
49+
50+
Implement it using your platform’s local storage (e.g. `DataStore`, `SharedPreferences`, `NSUserDefaults`, file system, etc).
51+
52+
---
53+
54+
### 2. Initialize the Cache
55+
56+
```kotlin
57+
fun main() {
58+
val store: Store = MyMultiplatformStore()
59+
Cache.initialize(store)
60+
}
61+
```
62+
63+
Optionally, provide a custom `Logger`:
64+
65+
```kotlin
66+
Cache.initialize(store, logger = MyLogger())
67+
```
68+
69+
---
70+
71+
### 3. Define and Use Cache Keys
72+
73+
Use built-in key helpers or define your own:
74+
75+
```kotlin
76+
val userKey = stringCacheKey("user_profile")
77+
val ageKey = integerCacheKey("user_age")
78+
```
79+
80+
---
81+
82+
### 4. Cache a Flow with Strategy
83+
84+
```kotlin
85+
flow { emit(fetchUserProfileFromApi()) }
86+
.cache(userKey, CacheStrategyType.IF_HAVE)
87+
.collect { user -> println("User: $user") }
88+
```
89+
90+
---
91+
92+
## Cache Strategies
93+
94+
Choose how the cache behaves during a Flow emission:
95+
96+
| Strategy | Description |
97+
|---------------------|--------------------------------------------------------------|
98+
| `ONLY_CACHE` | Always use the cache. Throws if no value exists. |
99+
| `ONLY_REQUEST` | Always skip cache. Fetch fresh and optionally cache it. |
100+
| `IF_HAVE` *(default)* | Use cache if available, otherwise fallback to the flow. |
101+
102+
#### Extend with Your Own CacheStrategy
103+
104+
Implement the `CacheStrategy<T>` interface for full control:
105+
106+
```kotlin
107+
abstract class CacheStrategy <T> (
108+
protected val key: Key<T>,
109+
protected val cachedAfterLoad : Boolean
110+
) {
111+
abstract suspend fun execute(currentFlow: Flow<T>): Flow<T>
112+
}
113+
```
114+
115+
---
116+
117+
## Keys
118+
119+
Use the following factory functions to quickly define typed keys for common primitive types:
120+
121+
| Key Type | Factory Function | Example |
122+
|----------|--------------------------|------------------------------------------|
123+
| `String` | `stringCacheKey(name)` | `val key = stringCacheKey("username")` |
124+
| `Int` | `integerCacheKey(name)` | `val key = integerCacheKey("user_age")` |
125+
| `Float` | `floatCacheKey(name)` | `val key = floatCacheKey("user_score")` |
126+
| `Boolean`| `booleanCacheKey(name)` | `val key = booleanCacheKey("is_logged")` |
127+
128+
These keys inherit from `Key<T>` and include built-in logic to handle type-safe caching operations.
129+
130+
#### Custom Key Example
131+
132+
You can also define your own cache key for complex or custom types:
133+
134+
```kotlin
135+
class MyKey(name: String): Key<MyType>(name) {
136+
override fun isTypeOf(valueClass: KClass<*>) = valueClass == MyType::class
137+
override suspend fun getFromStore(store: Store): Flow<MyType?> = ...
138+
override suspend fun saveToStore(item: MyType, store: Store) = ...
139+
}
140+
```

app/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

app/build.gradle.kts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
plugins {
2+
alias(libs.plugins.android.application)
3+
alias(libs.plugins.kotlin.android)
4+
}
5+
6+
android {
7+
namespace = "com.dapadz.cachedflow"
8+
compileSdk = 35
9+
10+
defaultConfig {
11+
applicationId = "com.dapadz.cachedflow"
12+
minSdk = 24
13+
targetSdk = 35
14+
versionCode = 1
15+
versionName = "1.0"
16+
17+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
18+
}
19+
20+
buildTypes {
21+
release {
22+
isMinifyEnabled = false
23+
proguardFiles(
24+
getDefaultProguardFile("proguard-android-optimize.txt"),
25+
"proguard-rules.pro"
26+
)
27+
}
28+
}
29+
compileOptions {
30+
sourceCompatibility = JavaVersion.VERSION_11
31+
targetCompatibility = JavaVersion.VERSION_11
32+
}
33+
kotlinOptions {
34+
jvmTarget = "11"
35+
}
36+
}
37+
38+
dependencies {
39+
implementation(libs.androidx.core.ktx)
40+
implementation(libs.androidx.appcompat)
41+
implementation(libs.material)
42+
}

app/proguard-rules.pro

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile

app/src/main/AndroidManifest.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools">
4+
5+
<application
6+
android:allowBackup="true"
7+
android:dataExtractionRules="@xml/data_extraction_rules"
8+
android:fullBackupContent="@xml/backup_rules"
9+
android:icon="@mipmap/ic_launcher"
10+
android:label="@string/app_name"
11+
android:roundIcon="@mipmap/ic_launcher_round"
12+
android:supportsRtl="true"
13+
android:theme="@style/Theme.CachingFlow"
14+
tools:targetApi="31" />
15+
16+
</manifest>

0 commit comments

Comments
 (0)