Rapidly fast and lightweight re-implementation of SharedPreferences which stores each preference in files separately, performs disk operations via NIO with memory mapped byte buffers and works IPC (between processes). Written from scratch.
Please note that api is not finalized yet and serialization contract or
public api may be changed prior 1.0.0
.
- Lightweight. Zero dependency
- Super fast (faster than any other key/value solutions)
- Small memory footprint while serialize/deserialize data
- Zero copy in-memory cache
- Persists only binary data. Not XML or JSON
- Out of box data encryption support
- Fully backward compatible with default
SharedPreferences
interface - Store all primitives include
double
,char
,byte
andshort
- Store complex data objects backward-compatible (see
Persistable
class documentation) - Fully optimized IPC support (preferences change listeners and in-memory cache works between processes)
- Handle various exception events
Preferences preferences = new BinaryPreferencesBuilder(context)
.build();
Please, use only one instance of preferences by name, it saves you from non-reasoned allocations. You can store one instance of preferences in application class or event better use one instance from IoC like Dagger or some another DI framework.
All parameters are optional and chain-buildable.
Builder contains method which defines desirable preferences name:
Preferences preferences = new BinaryPreferencesBuilder(context)
.name("user_data")
.build();
Default is "default" name.
You can define your own file vice versa encryption or use default:
Preferences preferences = new BinaryPreferencesBuilder(context)
.encryption(new AesByteEncryptionImpl("16 bytes secret key".getBytes(), "16 bytes initial vector".getBytes()))
.build();
Default is no-op encryption. Library also provides AesByteEncryptionImpl
implementation.
You can listen exceptions which comes during disk IO, serialization, task execution operations:
Preferences preferences = new BinaryPreferencesBuilder(context)
.exceptionHandler(new ExceptionHandler() {
@Override
public void handle(Exception e) {
//perform metrica report
}
})
.build();
Default is print handler which performs e.printStacktrace()
if
exception event are comes.
If your app architecture is process based (services works in separate processes) and you would like to get preferences updates with consistent cache state you can enable this feature:
Preferences preferences = new BinaryPreferencesBuilder(context)
.supportInterProcess(true)
.build();
Please, note that one key change delta should be less than 1 (one) megabyte because IPC data transferring is limited by this capacity. Details here: Documentation
Persistable
contract been added for fast and flexible saving and it's
restoring complex objects. It's pretty similar like standard java
Externalizable
contract but without few methods which don't need for.
For usage you just need to implement this interface with methods in your
data-model.
All Persistable data-objects should be registered by key for understanding de/serialization contract during cache initialization.
Preferences preferences = new BinaryPreferencesBuilder(context)
.registerPersistable(TestUser.KEY, TestUser.class)
.registerPersistable(TestOrder.KEY, TestOrder.class)
.build();
Note about deepClone
method: you should implement full object hierarchy copying
for fast immutable in-memory data fetching.
Sample for explanation: TestUser.java
You can dump your preferences with adb console command right in logcat:
adb shell am broadcast -a com.ironz.binaryprefs.ACTION_DUMP_PREFERENCE --es "pref_name" "your_pref_name" (optional: --es "pref_key" "your_pref_key")
where:
your_pref_name
- is your preferences name which is defined in register
method.
your_pref_key
- is your preference key, this is optional value.
How to register preferences by name:
DumpReceiver.register(name, preferences);
Fully working example of all values dump:
adb shell am broadcast -a com.ironz.binaryprefs.ACTION_DUMP_PREFERENCE --es "pref_name" "user_data"
Example only for user_id
key dump:
adb shell am broadcast -a com.ironz.binaryprefs.ACTION_DUMP_PREFERENCE --es "pref_name" "user_data" --es "pref_key" "user_id"
Please note that if you create multiple instances of one preferences
(e.g. in Activity#onCreate
) you should unregister dump
(e.g. in Activity#onDestroy
) like this:
DumpReceiver.unregister(name);
Disk I/O encrypt.completedIPCcompletedExternalizable.completed asPersistable
Preferences tooling (key set reading).completed:adb shell am broadcast -a com.ironz.binaryprefs.ACTION_DUMP_PREFERENCE --es "pref_name" "your_pref_name" (optional: --es "pref_key" "your_pref_key")
Custom serializers.completedSynchronous commits.completedStore all primitives (like byte, short, char, double).completedLock free (avoid locks).completed asLockFactory
.Exact background tasks for each serialization strategies.completedReduce events (implement events transaction).completed.Simplify api (instance creating, exception handles).completed- Finalize serialization and persistence contract
- Background initializer
byte[]
support- Default preferences migration mechanism
- IPC transactions without 1mb limit
- File name encrypt
Persistable
upgrade/downgrade api- RxJava support
sun.misc.Unsafe
serialization mode for api 21+
Copyright 2017 Alexander Efremenkov
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.