从0到1打造一款安卓app之13-集成数据库框架-ObjectBox

从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.其他资料

其他资料请参考官网说明

猜你喜欢

转载自juejin.im/post/7109103547404910605