从0到1打造一款安卓app之13-集成数据库框架-ObjectBox
为什么是ObjectBox而不是Jetpack的Room,因为它支持很多平台,在Flutter里也有相应的支持。
1.添加依赖
根build.gradle
里添加objectbox-gradle-plugin
buildscript {
ext.objectboxVersion = "3.1.3"
repositories {
mavenCentral()
// Note: 2.9.0 and older are available on jcenter()
}
dependencies {
// Android Gradle Plugin 3.3.0 or later supported.
classpath("com.android.tools.build:gradle:7.1.3")
classpath("io.objectbox:objectbox-gradle-plugin:$objectboxVersion")
}
}
复制代码
app模块的build.gradle
添加kapt和相关依赖
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'org.jetbrains.kotlin.kapt'
}
复制代码
dependencies {
debugImplementation("io.objectbox:objectbox-android-objectbrowser:$objectboxVersion")
releaseImplementation("io.objectbox:objectbox-android:$objectboxVersion")
implementation("io.objectbox:objectbox-kotlin:$objectboxVersion")
}
//这一句一定要写在依赖后面
apply plugin: 'io.objectbox'
复制代码
2.初始化ObjectBox
App Bundle, split APKs and LinkageError - ObjectBox Docs
@Entity
data class TestObjectBoxEntity(@Id var id: Long = 0, var name: String? = null)
var boxStore: BoxStore? = null
class ObjectBoxInitialzer : Initializer<Unit> {
override fun create(context: Context) {
LogUtils.d(Initializer::class.java.simpleName, "ObjectBoxInitialzer create")
try {
boxStore = MyObjectBox.builder()
.androidContext(context)
.build()
if (BuildConfig.DEBUG) {
//开启调试。可以直接从网页上查看数据库数据
val started = Admin(boxStore).start(context)
LogUtils.d(Initializer::class.java.simpleName, "Admin started :$started")
}
} catch (e: Exception) {
LogUtils.e(Initializer::class.java.simpleName, e.toString())
}
}
override fun dependencies(): MutableList<Class<out Initializer<*>>> {
return mutableListOf()
}
}
复制代码
3.实体类的继承
如果多个数据库类有相同的属性,可以定义一个基类,然后数据库里的字段子类和父类的字段都持久化到数据库
使用 @BaseEntity
注解基类,子类使用@Entity
注解并继承基类
@BaseEntity
abstract class Base {
@Id
var id: Long = 0
var baseString: String? = null
constructor()
constructor(id: Long, baseString: String?) {
this.id = id
this.baseString = baseString
}
}
// Subclass:
@Entity
class Sub : Base {
var subString: String? = null
constructor()
constructor(id: Long,
baseString: String?,
subString: String?) : super(id, baseString) {
this.subString = subString
}
}
复制代码
上面的方法需要定义次构函数,非常麻烦,下面这样写暂时也没有发现问题
@BaseEntity
abstract class BaseDBEntity(
@Id
var id: Long = 0,
var tableName: String? = null,
var objectId: String? = null,
var createdAt: String = TimeUtils.date2String(Date()),
var updatedAt: String = TimeUtils.date2String(Date()),
var createdAtTime: Long = Date().time,
var updatedAtTime: Long = Date().time,
)
复制代码
@Entity
class UserBean(baseString: String?,): BaseDBEntity()
复制代码
4.objectbox与Android Jetpack
对LiveData的支持
public class ObjectBoxLiveData<T> extends LiveData<List<T>> {
private final Query<T> query;
private DataSubscription subscription;
private final DataObserver<List<T>> listener = this::postValue;
public ObjectBoxLiveData(Query<T> query) {
this.query = query;
}
@Override
protected void onActive() {
// called when the LiveData object has an active observer
if (subscription == null) {
subscription = query.subscribe().observer(listener);
}
}
@Override
protected void onInactive() {
// called when the LiveData object doesn't have any active observers
if (!hasObservers()) {
subscription.cancel();
subscription = null;
}
}
}
复制代码
使用时,把query传递给ObjectBoxLiveData构造函数即可
noteLiveData = new ObjectBoxLiveData<>(notesBox.query().order(Note_.text).build());
对Paging的支持
public class NotePagedViewModel extends ViewModel {
private LiveData<PagedList<Note>> noteLiveDataPaged;
public LiveData<PagedList<Note>> getNoteLiveDataPaged(Box<Note> notesBox) {
if (noteLiveDataPaged == null) {
// query all notes, sorted a-z by their text
Query<Note> query = notesBox.query().order(Note_.text).build();
// build LiveData
noteLiveDataPaged = new LivePagedListBuilder<>(
new ObjectBoxDataSource.Factory<>(query),
20 /* page size */
).build();
}
return noteLiveDataPaged;
}
}
复制代码
5.objectbox与kotlin
引入依赖
dependencies {
implementation("io.objectbox:objectbox-kotlin:$objectboxVersion")
}
复制代码
对kotlon的Flow支持
// Listen to all changes to a Box
val flow = store.subscribe(TestEntity::class.java).toFlow()
// Get the latest query results on any changes to a Box
val flow = box.query().subscribe().toFlow()
复制代码
对kotlin的coroutine协程支持
suspend fun putNote(
note: Note,
dispatcher: CoroutineDispatcher
) = withContext(dispatcher) {
boxStore.boxFor(Note::class.java).put(note)
}
复制代码
// Calls callInTxAsync behind the scenes.
val id = boxStore.awaitCallInTx {
box.put(Note("Hello", 1))
}
复制代码
6.其他资料
其他资料请参考官网说明