Skip to content
/ ormkv Public
forked from lwj1994/ormkv

A pure Android orm-key value util

Notifications You must be signed in to change notification settings

famik/ormkv

 
 

Repository files navigation

Ormkv is a Object Relational Mapping keyValue-saving helper. It automatically generates object-oriented tool class that access key-value pairs based on the bean class.

Usage

    allprojects {
        repositories {
          ...
          maven { url 'https://jitpack.io'}
        }
    }
    
    dependencies {
	   def ormkvVersion = '3.0.3'
	   implementation "com.github.famik.ormkv:core:${ormkvVersion}"
	   
	   // if you use SharedPreferences
	   implementation "com.github.famik.ormkv:sp:${ormkvVersion}"
	   
	   // if you use MMKV
	   implementation "com.github.famik.ormkv:mmkv:${latestVersion}"
	   
	   // if you use kapt
	   kapt "com.github.famik.ormkv:compiler:${ormkvVersion}"
	   
	   // if you use ksp
	   ksp "com.github.famik.ormkv:compiler:${ormkvVersion}"
	}

Create key-value store class

package com.lwjlol.ormkv.demo

import android.content.Context
import com.lwjlol.ormkv.mmkv.MmkvHandler
import com.lwjlol.ormkv.sp.SharedPreferencesHandler

object KvStore {
    //  if you use SharedPreferences, you can use SharedPreferencesHandler
    val sharedPreferencesHandler =
        SharedPreferencesHandler(App.context.getSharedPreferences("SP", Context.MODE_PRIVATE))

    //  if you use mmkv, you can use MmkvHandler
    val mmkvHandler = MmkvHandler(com.tencent.mmkv.MMKV.defaultMMKV())
}

you can write your custom handler implement OrmKvHandler class

class MyHandler : OrmKvHandler {
    // TODO: implement set an get method
}

Create KvClass class

use @KvClass annotation this class.

@KvClass(
    name = "UserRegistry", // default name is className with suffix 'Registry', such as UserModelRegistry
    handler = "KvHandler.getDefault()",  // default handler is use ServiceLoader to found
    superclass = true // as superclass, use constructor arguments as default value
)
open class UserModel(
    // KvField defaultValue is ignored for superclass specified
    @KvField(defaultValue = "\"ignored\"")
    open var name: String = "realDefaultValue",
    @Transient // ignore this property
    @KvField(defaultValue = "32")
    open var age: Int = Build.VERSION.SDK_INT,
    @KvField(defaultValue = "12312312", enableReset = false)
    open var id: Long = 0,
    @KvField(defaultValue = "false")
    open var isMan: Boolean = false
)

Build and generate Registry class

build project and we will get a Registry class.

/**
 * this class is generated by https://github.com/famik/ormkv for [com.lwjlol.ormkv.demo.UserModel],
 * Please don't modify it!
 */
public class UserRegistry : UserModel() {
    private val kvHandler: KvHandler = KvHandler.getDefault()

    public override var name: String
        get() = super.name
        set(`value`) {
            super.name = value
            kvHandler.set("name", value)
        }

    public override var id: Long
        get() = super.id
        set(`value`) {
            super.id = value
            kvHandler.set("id", value)
        }

    public override var isMan: Boolean
        get() = super.isMan
        set(`value`) {
            super.isMan = value
            kvHandler.set("isMan", value)
        }

    init {
        refresh()
    }

    public fun refresh(): Unit {
        super.name = kvHandler.get("name", super.name)!!
        super.id = kvHandler.get("id", super.id)
        super.isMan = kvHandler.get("isMan", super.isMan)
    }

    public fun reset(): Unit {
        update(UserModel())
    }

    public override fun toString(): String = "name = $name"+
            "\nid = $id"+
            "\nisMan = $isMan"

    public fun update(model: UserModel): Unit {
        name = model.name
        id = model.id
        isMan = model.isMan
    }

    public fun toModel(): UserModel = UserModel(
        name = name,
        age = super.age,
        id = id,
        isMan = isMan)
}

Set/get value

Use the Registry instance to set/get value.

If you want to use singleton, you can set @KvClass annotation's singleton to true.

val user = UserRegistry()
user.name = "Mike"

Log.d(tag, user.toString())
Log.d(tag, user.name)

// refresh all values
user.refresh()

KSP

KSP Generated Sources in IDE Note, that as of the current KSP version generated java sources are detected by the IDE but NOT generated kotlin sources. This means that generated epoxy kotlin extensions will not automatically be resolved in the IDE. You must manually configure your source sets to include ksp generated folders.

You can add this to your root build.gradle file to work around this

subprojects { project ->
    afterEvaluate {
        if (project.hasProperty("android")) {
            android {
                if (it instanceof com.android.build.gradle.LibraryExtension) {
                    libraryVariants.all { variant ->
                        def outputFolder = new File("build/generated/ksp/${variant.name}/kotlin")
                        variant.addJavaSourceFoldersToModel(outputFolder)
                        android.sourceSets.getAt(variant.name).java {
                            srcDir(outputFolder)
                        }
                    }
                } else if (it instanceof com.android.build.gradle.AppExtension) {
                    applicationVariants.all { variant ->
                        def outputFolder = new File("build/generated/ksp/${variant.name}/kotlin")
                        variant.addJavaSourceFoldersToModel(outputFolder)
                        android.sourceSets.getAt(variant.name).java {
                            srcDir(outputFolder)
                        }
                    }
                }
            }
        }
    }
}

Of if you use kotlin build files you can apply it like this to a project.

/**
 * Return the Android variants for this module, or error if this is not a module with a known Android plugin.
 */
fun Project.requireAndroidVariants(): DomainObjectSet<out com.android.build.gradle.api.BaseVariant> {
 return androidVariants() ?: error("no known android extension found for ${project.name}")
}

/**
 * Return the Android variants for this module, or null if this is not a module with a known Android plugin.
 */
fun Project.androidVariants(): DomainObjectSet<out com.android.build.gradle.api.BaseVariant>? {
 return when (val androidExtension = this.extensions.findByName("android")) {
  is com.android.build.gradle.LibraryExtension -> {
   androidExtension.libraryVariants
  }
  is com.android.build.gradle.AppExtension -> {
   androidExtension.applicationVariants
  }
  else -> null
 }
}

fun Project.registerKspKotlinOutputAsSourceSet() {
 afterEvaluate {
  val android by lazy {
   extensions.findByType(com.android.build.gradle.BaseExtension::class.java)
    ?: throw NullPointerException()
  }

  requireAndroidVariants().forEach { variant ->
   val variantName = variant.name
   val outputFolder = File("build/generated/ksp/$variantName/kotlin")
   variant.addJavaSourceFoldersToModel(outputFolder)
   android.sourceSets.getAt(variantName).java {
    srcDir(outputFolder)
   }
  }
 }
}

About

A pure Android orm-key value util

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Kotlin 86.4%
  • Java 13.6%