Android Rxjava 3、Rxjava 2和多个调用问题
我在实现RxJava3/2时遇到困难,我需要完成的是: 一般的想法是将云数据库同步到设备上的SqLite数据库(房间)。 数据库可能会变大,大约100000个寄存器或更多,因此同步过程可能需要一些时间,我的第一次尝试是在一个请求中完成,并获取所有寄存器,然后将它们保存到SqLite(Room),但在某些情况下,这取决于设备生成的一些内存不足异常,因此经过一些研究,我发现RxJava就是答案,还实现了一些API调用分页Android Rxjava 3、Rxjava 2和多个调用问题,android,retrofit2,android-room,rx-java3,Android,Retrofit2,Android Room,Rx Java3,我在实现RxJava3/2时遇到困难,我需要完成的是: 一般的想法是将云数据库同步到设备上的SqLite数据库(房间)。 数据库可能会变大,大约100000个寄存器或更多,因此同步过程可能需要一些时间,我的第一次尝试是在一个请求中完成,并获取所有寄存器,然后将它们保存到SqLite(Room),但在某些情况下,这取决于设备生成的一些内存不足异常,因此经过一些研究,我发现RxJava就是答案,还实现了一些API调用分页 首先,我试图做一个概念验证,启动第一个改装呼叫,并在活动中显示响应,但我一直无
java.lang.ClassCastException:io.reactivex.rxjava3.internal.observators.LambdaObserver无法强制转换为io.reactivex.rxjava3.core.Observable
//Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.8.1'
implementation 'com.squareup.retrofit2:converter-gson:2.8.1'
//Retrofit2 Adapter for RxJava 3
implementation "com.github.akarnokd:rxjava3-retrofit-adapter:3.0.0"
//okhttp3 Logging Interceptor
implementation "com.squareup.okhttp3:logging-interceptor:4.5.0"
//RxJava
implementation "io.reactivex.rxjava3:rxjava:3.0.2"
implementation 'io.reactivex.rxjava3:rxandroid:3.0.
类项目
public class Item {
private String epc;
private String barcode;
private String name;
private String description;
private String brand;
@SerializedName("serial_number")
private String serialNumber;
private double cost;
@SerializedName("fk_item_state")
private int status;
@SerializedName("fk_category")
private int category;
@SerializedName("fk_location")
private int location;
private String parent;
@SerializedName("responsable")
private String responsible;
@SerializedName("purchase_date")
private String purchaseDate;
@SerializedName("creation_date")
private String creationDate;
@SerializedName("last_update")
private String lastUpdate;
@SerializedName("inventory_date")
private String inventoryDate;
@SerializedName("last_seen")
private String lastSeen;
...
类ItemSyncDetails
public class ItemSyncDetails {
@SerializedName("CurrentPage")
int currentPage;
@SerializedName("PageCount")
int pageCount;
@SerializedName("PageSize")
int pageSize;
@SerializedName("RecordCount")
int recordCount;
@SerializedName("Results")
List<Item> mItemList;
...
用于-
提前谢谢,我真的很感谢你的帮助。
我对课堂活动做了一些改变
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
...
public class MainActivity extends AppCompatActivity {
private TextView tvResult;
private Button send;
private ProgressDialog mProgressDialog;
private ItemSyncDetails mItemSyncDetails;
private List<Item> mItemsList;
private CompositeDisposable disposables = new CompositeDisposable();
private FrekuencyApi frekuencyApi;
private Retrofit retrofit;
private int mNumPages;
private CompositeDisposable compositeDisposable;
private HttpLoggingInterceptor logging;
private static final String TAG = "MainActivity";
private Object handleResults;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult = findViewById(R.id.tv_result);
send = findViewById(R.id.btnSend);
mItemSyncDetails = new ItemSyncDetails();
mProgressDialog = new ProgressDialog(this);
mItemsList = new ArrayList<Item>();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addNetworkInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.build();
return chain.proceed(request);
}
}).build();
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.10:82/api/v1.0/")
.client(client)
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//TODO: EVENTO AL HACER CLICK EN BOTON
getRecordsCount();
}
});
}
private void getRecordsCount(){
FrekuencyApi frekuencyApi = retrofit.create(FrekuencyApi.class);
Observable<ItemSyncDetails> observable = (Observable<ItemSyncDetails>) frekuencyApi.getRecordsCount(1,1,1)
.subscribeOn(Schedulers.io())
.retry(3)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::HandleResults, this::handleError );
}
private void HandleResults(ItemSyncDetails itemSyncDetails) {
this.mItemSyncDetails = itemSyncDetails;
int pageSize = 100;
int numPages = itemSyncDetails.getPageCount()/pageSize;
if (itemSyncDetails.getRecordCount() < pageSize || itemSyncDetails.getRecordCount()%pageSize != 0){
numPages++;
}
this.mNumPages = numPages;
tvResult.append("Page size: " + pageSize + "\n");
tvResult.append("Page number: " + this.mNumPages + "\n");
tvResult.append("Total items: " + itemSyncDetails.getRecordCount() + "\n");
}
private void handleError(Throwable throwable) {
Log.e("Observer", ""+ throwable.toString());
Toast.makeText(this, "ERROR DE CONEXION",
Toast.LENGTH_LONG).show();
}
...
public class MainActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult = findViewById(R.id.tv_result);
send = findViewById(R.id.btnSend);
mItemSyncDetails = new ItemSyncDetails();
mProgressDialog = new ProgressDialog(this);
mItemsList = new ArrayList<Item>();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addNetworkInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.build();
return chain.proceed(request);
}
}).build();
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.10:82/api/v1.0/")
.client(client)
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showProgressDialog("Items");
getRecordsCount();
}
});
}
private void getRecordsCount(){
retrofit.create(FrekuencyApi.class)
.getRecordsCount(1,1,1)
.subscribeOn(Schedulers.io())
.retry(3)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::HandleResults, this::handleError,this::getNumPagesHandlerComplete );
}
private void HandleResults(ItemSyncDetails itemSyncDetails) {
this.mItemSyncDetails = itemSyncDetails;
int pageSize = 100;
int numPages = itemSyncDetails.getRecordCount()/pageSize;
if (itemSyncDetails.getRecordCount() < pageSize || itemSyncDetails.getRecordCount()%pageSize != 0){
numPages++;
}
this.mNumPages = numPages;
tvResult.append("Tamaño de pagina: " + pageSize + "\n");
tvResult.append("Numero de paginas: " + this.mNumPages + "\n");
tvResult.append("Numero total de registros: " + itemSyncDetails.getRecordCount() + "\n");
}
private void getNumPagesHandlerComplete() {
getAllRecords(mNumPages);
}
private void getAllRecords(int numPages){
frekuencyApi = retrofit.create(FrekuencyApi.class);
//numPages: total of pages are the number of times to send the request to API
Observable.range(1, numPages)
.concatMap(i -> frekuencyApi.getItemsPageDetails(100,i,1))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::getAllHandleResults, this::handleError,this::handleComplete);
}
private void getAllHandleResults(ItemSyncDetails itemSyncDetails) {
//TODO: Should it be the right place to save data to DB?
//Get the progress
int tmp = getProgress(itemSyncDetails.getPageCount(),
itemSyncDetails.getCurrentPage(),itemSyncDetails.getPageSize());
//Update ProgressDialog Progress
mProgressDialog.setProgress(tmp);
tvResult.setText("Progreso: "+ tmp + "%\n");
if (itemSyncDetails.getCurrentPage() == itemSyncDetails.getPageCount()){
//Showing on screen when last request is done
tvResult.append("******************\n");
tvResult.append(itemSyncDetails.getItemList().toString());
tvResult.append("******************\n");
}
}
private void handleComplete() {
//when the last request finished
tvResult.append("\nProceso de Sincronizacion terminado con exito!");
closeProgressDialog();
}
private void handleError(Throwable throwable) {
Log.e("Observer", ""+ throwable.toString());
tvResult.append("\n******************\n");
tvResult.append("ERROR DE CONEXION...\n");
tvResult.append(throwable.toString());
Toast.makeText(this, "ERROR DE CONEXION",
Toast.LENGTH_LONG).show();
closeProgressDialog();
}
...
public类MainActivity扩展了AppCompatActivity{
...
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult=findViewById(R.id.tv_结果);
send=findviewbyd(R.id.btnSend);
mItemSyncDetails=新项目SyncDetails();
mProgressDialog=新建进度对话框(此);
mItemsList=新的ArrayList();
HttpLoggingInterceptor拦截器=新的HttpLoggingInterceptor();
拦截器.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient客户端=新建OkHttpClient.Builder()
.addInterceptor(拦截器)
.addNetworkInterceptor(新的Interceptor(){
@凌驾
公共okhttp3.响应截获(链)引发IOException{
请求=chain.Request().newBuilder()
.build();
返回链。继续(请求);
}
}).build();
改装=新改装.Builder()
.baseUrl(“http://192.168.1.10:82/api/v1.0/")
.客户(客户)
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
send.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
showProgressDialog(“项目”);
getRecordsCount();
}
});
}
私有void getRecordsCount(){
create(FrekuencyApi.class)
.getRecordsCount(1,1,1)
.subscribeOn(Schedulers.io())
.重试(3)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::HandleResults,this::handleError,this::getNumPagesHandlerComplete);
}
私有无效句柄结果(ItemSyncDetails ItemSyncDetails){
this.mItemSyncDetails=itemSyncDetails;
int pageSize=100;
int numPages=itemSyncDetails.getRecordCount()/pageSize;
如果(itemSyncDetails.getRecordCount()frekuencyApi.getItemsPageDetails(100,i,1))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::GetAllHandlerResults,this::handleError,this::handleComplete);
}
私有void GetAllHandlerResults(ItemSyncDetails ItemSyncDetails){
//TODO:它应该是将数据保存到DB的正确位置吗?
//取得进展
int tmp=getProgress(itemSyncDetails.getPageCount(),
itemSyncDetails.getCurrentPage(),itemSyncDetails.getPageSize());
//更新进度对话框进度
mProgressDialog.setProgress(tmp);
tvResult.setText(“Progreso:+tmp+“%\n”);
如果(itemSyncDetails.getCurrentPage()==itemSyncDetails.getPageCount()){
//上次请求完成时在屏幕上显示
tvResult.append(“************************\n”);
追加(itemSyncDetails.getItemList().toString());
tvResult.append(“************************\n”);
}
}
私有无效处理完成(){
//最后一个请求何时完成
tvResult.append(“\nProceso de Sincronizacion terminado con exito!”);
closeProgressDialog();
}
私有无效句柄错误(可丢弃可丢弃){
Log.e(“Observer”,“throwable.toString());
tvResult.append(“\n*********************\n”);
tvResult.append(“连接错误…\n”);
tvResult.append(throwable.toString());
Toast.makeText(这是“连接错误”,
Toast.LENGTH_LONG).show();
closeProgressDialog();
}
...
对于MainActivity类的更改,基本上有两个方法getRecordsCount()和getAllRecords(int numPages),每个方法都触发一个RX Java调用
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.frekuency.retrofitapptest, PID: 9120
java.lang.ClassCastException: io.reactivex.rxjava3.internal.observers.LambdaObserver cannot be cast to io.reactivex.rxjava3.core.Observable
at com.frekuency.retrofitapptest.views.MainActivity.getRecordsCount(MainActivity.java:110)
at com.frekuency.retrofitapptest.views.MainActivity.access$000(MainActivity.java:39)
at com.frekuency.retrofitapptest.views.MainActivity$2.onClick(MainActivity.java:98)
at android.view.View.performClick(View.java:5273)
at android.view.View$PerformClick.run(View.java:21315)
at android.os.Handler.handleCallback(Handler.java:743)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5659)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:822)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712)
D/OkHttp: --> GET http://192.168.1.10:82/api/v1.0/item?pageSize=1¤tPage=1&sortBy=1
--> END GET
I/Process: Sending signal. PID: 9120 SIG: 9
I/System: core_booster, getBoosterConfig = false
{
Results: [
{
epc: "202020202020202030303031",
barcode: "0001",
name: "Televisor Samnsung",
description: "0001",
creation_date: "2020-02-26T10:55:06",
last_update: "2020-02-26T10:55:06",
last_seen: "2020-02-26T10:55:06",
brand: "Samnsung",
serial_number: "0001",
parent: "",
fk_category: 1,
responsable: "",
purchase_date: "2020-02-26T10:55:06",
cost: 0,
fk_location: 1008,
fk_item_state: 1,
inventory_date: "2020-02-26T10:55:06"
}
],
CurrentPage: 1,
PageCount: 65565,
PageSize: 1,
RecordCount: 65565
}
public class MainActivity extends AppCompatActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvResult = findViewById(R.id.tv_result);
send = findViewById(R.id.btnSend);
mItemSyncDetails = new ItemSyncDetails();
mProgressDialog = new ProgressDialog(this);
mItemsList = new ArrayList<Item>();
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.addNetworkInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request().newBuilder()
.build();
return chain.proceed(request);
}
}).build();
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.1.10:82/api/v1.0/")
.client(client)
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showProgressDialog("Items");
getRecordsCount();
}
});
}
private void getRecordsCount(){
retrofit.create(FrekuencyApi.class)
.getRecordsCount(1,1,1)
.subscribeOn(Schedulers.io())
.retry(3)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::HandleResults, this::handleError,this::getNumPagesHandlerComplete );
}
private void HandleResults(ItemSyncDetails itemSyncDetails) {
this.mItemSyncDetails = itemSyncDetails;
int pageSize = 100;
int numPages = itemSyncDetails.getRecordCount()/pageSize;
if (itemSyncDetails.getRecordCount() < pageSize || itemSyncDetails.getRecordCount()%pageSize != 0){
numPages++;
}
this.mNumPages = numPages;
tvResult.append("Tamaño de pagina: " + pageSize + "\n");
tvResult.append("Numero de paginas: " + this.mNumPages + "\n");
tvResult.append("Numero total de registros: " + itemSyncDetails.getRecordCount() + "\n");
}
private void getNumPagesHandlerComplete() {
getAllRecords(mNumPages);
}
private void getAllRecords(int numPages){
frekuencyApi = retrofit.create(FrekuencyApi.class);
//numPages: total of pages are the number of times to send the request to API
Observable.range(1, numPages)
.concatMap(i -> frekuencyApi.getItemsPageDetails(100,i,1))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::getAllHandleResults, this::handleError,this::handleComplete);
}
private void getAllHandleResults(ItemSyncDetails itemSyncDetails) {
//TODO: Should it be the right place to save data to DB?
//Get the progress
int tmp = getProgress(itemSyncDetails.getPageCount(),
itemSyncDetails.getCurrentPage(),itemSyncDetails.getPageSize());
//Update ProgressDialog Progress
mProgressDialog.setProgress(tmp);
tvResult.setText("Progreso: "+ tmp + "%\n");
if (itemSyncDetails.getCurrentPage() == itemSyncDetails.getPageCount()){
//Showing on screen when last request is done
tvResult.append("******************\n");
tvResult.append(itemSyncDetails.getItemList().toString());
tvResult.append("******************\n");
}
}
private void handleComplete() {
//when the last request finished
tvResult.append("\nProceso de Sincronizacion terminado con exito!");
closeProgressDialog();
}
private void handleError(Throwable throwable) {
Log.e("Observer", ""+ throwable.toString());
tvResult.append("\n******************\n");
tvResult.append("ERROR DE CONEXION...\n");
tvResult.append(throwable.toString());
Toast.makeText(this, "ERROR DE CONEXION",
Toast.LENGTH_LONG).show();
closeProgressDialog();
}
...