B4J Library [B4X] KVS2 / KeyValueStore 2 - Simple & Powerful Local Datastore

Status
Not open for further replies.
Recommended to use the newer b4xlib: https://www.b4x.com/android/forum/threads/b4x-kvs2-keyvaluestore2-library.120234/
KeyValueStore is a persistent key/value based data store. It is similar to the useful Map collection, however unlike Map which stores the data in memory, KVS stores the data in a database. This means that you don't need to worry about losing data or saving the state when the program ends.

This version replaces the older version. It is not backwards compatible. You cannot use it with databases created with the previous version.

The main differences between v2 and v1:
The new version is based on B4XSerializator to serialize the values and on B4XCipher to encrypt it.
This means that the data can be shared between B4A, B4J and B4i. For example you can create the data store in B4J and embed it in your mobile app.
B4XSerializator is also faster and simpler to use.

Using KVS is similar to using a Map. You initialize it once (use the Starter service in B4A) and then you can put or get items with Put, Get or GetDefault methods.
You can use PutEncrypted to encrypt the value before it is stored. Use GetEncrypted to get an encrypted value.
If you want to put bitmaps then use PutBitmap and GetBitmap.

The supported types of objects are:

Lists, Maps, Strings, primitives (numbers), user defined types and arrays (only arrays of bytes and arrays of objects are supported).
Custom types should be declared in the main module.
Including combinations of these types (a list that holds maps for example).

KeyValueStore depends on the following libraries: SQL, RandomAccessFile and B4XEncryption (iEncryption on B4i).
Note that in B4J you need to download the bouncy castle jar and add the following two lines to the main module:
B4X:
#AdditionalJar: sqlite-jdbc-3.7.2
#AdditionalJar: bcprov-jdk15on-154


A B4A example is attached. The class module is compatible with B4A, B4J and B4i.

Tip: Check CloudKVS for an auto-synchronizing solution: https://www.b4x.com/android/forum/threads/b4x-cloudkvs-synchronized-key-value-store.63536/#content

Updates:

- V2.20 - Adds support for GetMapAsync and PutMapAsync. These methods allow to asynchronously insert or retrieve multiple items.
Examples:
B4X:
'getting all items:
Wait For (Starter.kvs.GetMapAsync(Starter.kvs.ListKeys)) Complete (Result As Map)
Log(Result)
'getting specific items:
Wait For (Starter.kvs.GetMapAsync(Array("Key1", "Key2", "Key3")) Complete (Result As Map)
Log(Result)

Note that starting from B4A v8.0 KeyValueStore2 is included as an internal library.
 

Attachments

  • B4A_KVS2.zip
    9.8 KB · Views: 2,887
  • KeyValueStore.bas
    4.8 KB · Views: 2,570
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
As the documentation says:
The supported types of objects are:

Lists, Maps, Strings, primitives (numbers), user defined types and arrays (only arrays of bytes and arrays of objects are supported).
Custom types should be declared in the main module.
Including combinations of these types (a list that holds maps for example).

Putting an unsupported object in a Map or List will not help.
 

LucaMs

Expert
Licensed User
Longtime User
As the documentation says:
...
Putting an unsupported object in a Map or List will not help.
It's hard to know which objects are supported, despite the documentation, at least for me (this is not a criticism of the documentation!).
Probably only bitmaps are treated differently, I don't see what else is not supported :) (bitmaps are also supportded, I know).


Well, I will watch the source
Almost a single Put; the fulcrum is the B4XSerializator, which is an Anywhere Software creation, I think, it isn't a wrapper.
Is it impossible to parse the object passed to it to check if this is (or contains) a bitmap and then... ?


Thank you
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
Any object other than numbers, strings, maps, lists or custom types is not supported by Put / Get methods.

PutBitmap / GetBitmap supports bitmaps.

Is it impossible to parse the object passed to it to check if this is (or contains) a bitmap and then... ?
Yes. You can go over your data and check whether there are bitmaps or not. If there is a bitmap then you will need to convert it to an array of bytes (see PutBitmap code).
 

LucaMs

Expert
Licensed User
Longtime User
Any object other than numbers, strings, maps, lists or custom types is not supported by Put / Get methods.

PutBitmap / GetBitmap supports bitmaps.


Yes. You can go over your data and check whether there are bitmaps or not. If there is a bitmap then you will need to convert it to an array of bytes (see PutBitmap code).
I know what to do; it would be great if B4XSerializator could do it :).

Thank you
 

susu

Well-Known Member
Licensed User
Longtime User
1. Is there away to PutBitmap and Encrypt it? Something like PutBitmapEncrypted.
2. I add only 1 bitmap (file size 59KB) but the datastore2 file increased to 204KB. How to reduce it?
Thanks.
 

DavideV

Active Member
Licensed User
Longtime User
Hi, i would save a custom type made of objects:

B4X:
Type BigButton(PnlBase As Panel, _                    'the container
                   Icon As ImageView, _                   'the icon
                    LblBase As Label, _                     'the label for short decription
                    Action As String)                         'the action for the button as json string

but when i put that type into a key i get an error : B4XSerializator can't serialize imageview (and the panel and label too, no problem with the string 'Action')

How can i achieve this with this class?

i need to retrieve the PnlBase and other informations later when the user clicks on the corresponding button.

thanks in advance!

DavideV
 

DavideV

Active Member
Licensed User
Longtime User
Thx Erel, if i well understand i must match the tag using something like getallviewrecursive and compare the tag of each view with the stored string?
 

LWGShane

Well-Known Member
Licensed User
Longtime User
@Erel - Please update the bouncy-castle URL. The file cannot be found. (Updated link provided by @Douglas Farias )
 

ilan

Expert
Licensed User
Longtime User
hi

i would like to use this class to store my custom type on my new b4i app. since i have no b4i in my work i am testing it on b4j but i am getting an error on compile

this is the whole code:

B4X:
#Region  Project Attributes
    #MainFormWidth: 600
    #MainFormHeight: 400
    #AdditionalJar: sqlite-jdbc-3.7.2
    #AdditionalJar: bcprov-jdk15on-154
#End Region

Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Type shift(istime As Boolean, datein As Long, shiftid As String, timein As String, timeout As String, break As Int, bonus As Double, dayspend As Double, dayinfo As String, totalhour As Long, totalwage As Double)
    Dim allshift As KeyValueStore
    Dim hw As Int = 25
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.SetFormStyle("UNIFIED")
    MainForm.Show
   
    allshift.Initialize(File.DirApp,"allshift.db")
   
    For i = 0 To 50
        Dim newshift As shift
        newshift.Initialize
        newshift.istime = False
        newshift.datein = DateTime.Now
        newshift.shiftid = "בוקר"
        newshift.timein = DateTime.Time(DateTime.Now)
        newshift.timeout = DateTime.Time(DateTime.Now+(Rnd(60,300)*60000))
        newshift.break = Rnd(0,30)
        newshift.bonus = 0
        newshift.dayspend = 0
        newshift.dayinfo = ""
        newshift.totalhour = DateTime.TimeParse(newshift.timein) + DateTime.TimeParse(newshift.timeout)
        newshift.totalwage = (newshift.totalhour*DateTime.TicksPerMinute) * (hw/60)
        allshift.Put(newshift.datein,newshift)
    Next

End Sub

and this is the error on complie

B4J version: 4.01
Parsing code. (0.00s)
Compiling code. (0.01s)
Compiling layouts code. (0.00s)
Compiling generated Java code. Error
javac 1.8.0_65
src\b4j\example\main.java:62: error: <identifier> expected
public int break;
^
1 error

i have downloaded bouncy-castle.jar and put it in the lib folder. am i doing something wrong?

thanx
 

ilan

Expert
Licensed User
Longtime User
i also figured out how to get the size of the KeyValueStore "Map"

B4X:
Public Sub Size As Int
    Return sql1.ExecQuerySingleResult("SELECT count(key) FROM main")
End Sub
 
Status
Not open for further replies.
Top