这个问题通常以很多方式被提出和解决,但是如果我回到同一问题,那是因为我有点困惑。这是我第一次处理Realm ORM。
此存储库类状态,用于数据库存储上的实现。以Realm和ApiService为例
class LoginRepositoryImpl(var realm: Realm, var apiService: ApiService){
override fun doLogin(email: String, password: String) {
apiService.loginCheck(email, password)
.flatMap { t: EntityToken ->
// check if user already exist and delete it
val checkIfUserExist = getUserIfExist("email", email)
if (checkIfUserExist != null) {
realm.executeTransactionAsync {
checkIfUserExist.deleteFromRealm()
}
}
// insert user into DB
realm.executeTransactionAsync { bgRealm ->
val user = bgRealm.createObject(UserModel::class.java, UserModel.cachedNextId)
user.email = email
user.logged = true
}
// i want to make another request to server
return@flatMap apiService.pingServer(t.refresh_token)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ uR ->
// make update of user table
realm.executeTransactionAsync {
getUserIfExist("email", email)?.fullname = uR.fullname
}
}
}
//function to check if user instance already exist
private fun getUserIfExist(field: String, email: String): UserModel? {
return realm.where(UserModel::class.java)
.equalTo(field, email)
.findFirstAsync()
}
}
Ps。帮助我解决来自错误线程的领域访问
答案 0 :(得分:0)
您可以在将使用Schedulers.single()
的领域上创建包装器。它将每次使用相同的线程。但是我认为我也必须从该线程获取Realm实例。
我这样做很丑
public long count() throws RealmException {
return Single.fromCallable(() -> realmService.getRealm().where(dataTypeClass).count())
.subscribeOn(Schedulers.single())
.blockingGet();
}
realmService.getRealm()返回仅延迟加载一次的Realm实例。
您还可以只返回Single
并使用RxJava链接调用。
答案 1 :(得分:0)
我认为我每次需要提出请求时都通过创建Realm的新实例来解决问题。
我将我的私有函数转换为此
private fun getUserIfExist(db: Realm, email: String): UserModel? {
return db.where(UserModel::class.java).equalTo("email", email).findFirst()
}
我为删除创建了一个新的私有函数
private fun deleteInDb(db: Realm, email: String) {
db.executeTransactionAsync {
it.where(UserModel::class.java)
.equalTo("email", email)
.findFirst()
}
}
要写入该表,我也创建了一个私有函数
private fun writeToDB(entityToken: EntityToken, email: String): String? {
realm = Realm.getDefaultInstance()
realm.executeTransactionAsync { bgRealm ->
var user = findInDb(bgRealm, email)
if (user != null) {
deleteInDb(bgRealm, email)
}
user = bgRealm.createObject(UserModel::class.java, UserModel.cachedNextId)
user!!.email = email
user.token = entityToken.token
user.refreshToken = entityToken.refresh_token
user.logged = true
}
realm.close()
return entityToken.refresh_token
}
最后我的doLogin函数变成了
override fun doLogin(email: String, password: String) {
apiService.loginCheck(email, password)
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.computation())
.map {
// write to DB
writeToDB(it, email, password)
return@map it
}
.flatMap { ping ->
//doPing to refresh token if not success
if (!ping.success) {
}
return@flatMap apiService.userInfoFromServer
}
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ uR ->
updateUserInfo(uR, email)
}, { error ->
Log.e("tt", error.message)
})
}
}
它有效,但我遇到了另一个问题。我只发送Realm对象的事实,所以当我声明
realm = Realm.getDefaultInstance()
它通过“默认名称”更改了我的RealmConfiguration“数据库名称”
欢迎所有解决方案!