我有一个带有Room
数据库的测试项目。使用Asynctask
,可以成功地将包含一些测试数据的对象插入数据库。我正在尝试学习RxJava
,并将Asynctask
替换为RxJava's
observer
,但这是行不通的。我已经阅读了许多文档并观看了教程,但我认为我不太明白。以下是相关代码:
在这里,将Room
中的数据设置为List
对象:
for(ObjectForArray item: listToDatabase) {
myRoomEntity.setName( item.getName() );
Log.d( "TAG", myRoomEntity.getName() );
}
然后,我尝试使用RxJava
Observable
将数据插入数据库。最初是使用Asynctask
成功完成的:
Observable<MyRoomEntity> myRX = Observable
.just(myRoomEntity)
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() );
myRX.subscribe( new Observer<MyRoomEntity>() {
@Override
public void onSubscribe(Disposable d) {
Log.d("TAG ONSUBSCRIBE", d.toString());
try {
myViewModel.insertDatabase( myRoomEntity );
Log.d( "TAG", "Populating database Success" );
}catch(Error error) {
Log.d( "TAG", error.toString() );
}
}
OnNext
,OnError
和OnComplete
为空。
当我运行项目时,它崩溃并显示错误:
Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
我显然使用RxJava
是错误的,因为重点是要在远离主线程的地方执行异步任务。
答案 0 :(得分:1)
由于尝试在主(UI)线程上插入对象而收到此错误。
您应该执行以下操作:
Observable.fromCallable(() -> myViewModel.insertDatabase( myRoomEntity ))
.subscribeOn( Schedulers.io() )
.observeOn( AndroidSchedulers.mainThread() );
然后使用观察者来订阅Observable。
答案 1 :(得分:0)
请尝试像这样重组代码:
Completable.fromAction(() -> myViewModel.insertDatabase(myRoomEntity))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(() -> Log.d("TAG", "Populating database Success"),
throwable -> Log.d("TAG", throwable.toString()))
注意事项:
defer
http://reactivex.io/documentation/operators/defer.html just
通话答案 2 :(得分:0)
我已使用RX Java代替Asyntask,因为它已在android 9中弃用 android提供了许多替代品,例如Executors,threads,Listenable Futures,Coroutines?,因此您正在寻找如何使用rxjava实现此功能以及RX Java java如何帮助您迁移,只需在gradle中首先添加这些依赖项即可。
implementation "io.reactivex.rxjava2:rxjava:2.2.20"
implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
一旦导入,就可以开始使用RX java了,我将让您知道可以在哪里放置后台任务,执行前,执行后异步任务
首先让我们开始使用Rx Java进行编码,我对方法的注释将帮助您放置代码
Observable.fromCallable(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
/// here is your background task
return true;
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
//// pre execute here is my progress dialog
showProgressDialog(getString(R.string.scanning));
}
@Override
public void onNext(Boolean aBoolean) {
//// here is on sucess you can do anystuff here like
if (aBoolean){
/// if its value true you can go ahead with this
}
}
@Override
public void onError(Throwable e) {
/// this helps you to go if there is any error show dialog whatever you wants here
Log.e("error of kind",e.getMessage() );
}
@Override
public void onComplete() {
/// when your task done means post execute
}
});
完成后,就可以开始实施了
Observable.fromCallable(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
/// here is your background task
uribitmap = getScannedBitmap(original, points);
uri = Utils.getUri(getActivity(), uribitmap);
scanner.onScanFinish(uri);
return true;
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
//// pre execute here is my progress dialog
showProgressDialog(getString(R.string.scanning));
}
@Override
public void onNext(Boolean aBoolean) {
//// here is on sucess you can do anystuff here like
if (aBoolean){
/// if its value true you can go ahead with this
}
}
@Override
public void onError(Throwable e) {
/// this helps you to go if there is any error show dialog whatever you wants here
Log.e("error of kind",e.getMessage() );
}
@Override
public void onComplete() {
/// when your task done means post execute
uribitmap.recycle();
dismissDialog();
}
});
现在我将与执行者一起执行此操作:
/// pre execute you can trigger to progress dialog
showProgressDialog(getString(R.string.scanning));
ExecutorService executors = Executors.newSingleThreadExecutor();
executors.execute(new Runnable() {
@Override
public void run() {
//// do background heavy task here
final Bitmap uribitmap = getScannedBitmap(original, points);
uri = Utils.getUri(getActivity(), uribitmap);
scanner.onScanFinish(uri);
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
//// Ui thread work like
uribitmap.recycle();
dismissDialog();
}
});
}
});