Android RX Observer al database SQLite non funziona
-
26-12-2019 - |
Domanda
Sto cercando di aggiungere un osservatore RX al mio database SQLITE e sto sicuramente mancando qualcosa dalla mia implementazione in quanto né i metodi onNext()
e onCompleted()
dal mio osservatore non vengono chiamati.
Ecco il mio osservatore:
private final Observer<List<Order>> mObjectiveObserver = new Observer<List<Order>>() {
@Override
public void onCompleted() {
System.out.println("Load completed");
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<Order> objectives) {
System.out.println("On Next: " + objectives.size() + " elements found!");
orderAdapter.clear();
if (objectives != null) {
orderAdapter.addAll(objectives);
mCirclePulseView.setVisibility(View.INVISIBLE);
} else {
mCirclePulseView.setVisibility(View.VISIBLE);
}
orderAdapter.notifyDataSetChanged();
}
};
.
Questi sono i miei metodi LoaderCallback
:
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
Loader<Cursor> loader = null;
switch (loaderId) {
case LOADER_ORDERS:
System.out.println("Create loader called");
loader = new CursorLoader(OrderManagerApplication.getAppContext(), OrderManagerContract.Order.CONTENT_URI,
QueryOrder.PROJECTION_SIMPLE, null, null, OrderManagerContract.Order.DATE_SORT);
break;
}
return loader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (getActivity() == null) {
return;
}
if (data != null && !data.isClosed()) {
System.out.println("Finished loading orders, data not null");
switch (loader.getId()) {
case LOADER_ORDERS:
if (subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
subscription = AndroidObservable
.bindFragment(this, DatabaseHelper.mainOrdersObservable(data))
.subscribeOn(Schedulers.computation())
.unsubscribeOn(AndroidSchedulers.mainThread())
.subscribe(mObjectiveObserver);
System.out.println("I should be here, onLoadFinished");
break;
}
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
.
Il codice del contenuto dell'osservatore segue sotto:
class HomeOrdersContentObserver extends ContentObserver {
private int mLoaderId = 0;
public HomeOrdersContentObserver(Handler handler, int loaderId) {
super(handler);
mLoaderId = loaderId;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
if (getActivity() == null) {
return;
}
Bundle bundle = new Bundle();
//bundle.putString(FILTER_TXT, lastFilterQ);
restartLoader(mLoaderId, bundle);
}
}
public void restartLoader(int loaderId, Bundle args) {
getLoaderManager().restartLoader(loaderId, args, this);
}
.
Ho messo i registri ovunque nel mio codice e vengono stampati come dovrebbero, ad eccezione dei metodi onNext
e onCompleted
.Qualche idea ciò che potrei mancare dalla mia implementazione?
Soluzione
Vedo alcuni problemi con il codice sopra.
1st: non stai effettivamente chiamando onnext / oncompleted ovunque. Dal momento che stai cercando di collegare i due paradigmi (Loader & RX), allora dovresti inserire il successivo in onloadFinited (con OnError nel caso in cui si desidera chiamare quando non ci sono dati, ma che chiuderà l'abbonamento) e acceso onloaderreset
2nd: stai rifissando l'abbonamento in onloadFinited, che non penso che vorresti - perché vorresti riscriverti ogni volta che hai nuovi dati? Dovresti farlo quando si crea il caricatore e annullare l'iscrizione quando si distrugge il caricatore (onloaderreset).
Questa è una possibile implementazione:
@Override
public Loader<Cursor> onCreateLoader(int loaderId, Bundle args) {
Loader<Cursor> loader = null;
switch (loaderId) {
case LOADER_ORDERS:
System.out.println("Create loader called");
loader = new CursorLoader(OrderManagerApplication.getAppContext(), OrderManagerContract.Order.CONTENT_URI,
QueryOrder.PROJECTION_SIMPLE, null, null, OrderManagerContract.Order.DATE_SORT);
if (subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
subscription = AndroidObservable
.bindFragment(this, DatabaseHelper.mainOrdersObservable(data))
.subscribeOn(Schedulers.computation())
.unsubscribeOn(AndroidSchedulers.mainThread())
.subscribe(mObjectiveObserver);
break;
}
return loader;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (getActivity() == null) {
return;
}
if (data != null && !data.isClosed()) {
System.out.println("Finished loading orders, data not null");
switch (loader.getId()) {
case LOADER_ORDERS:
mObjectiveObserver.onNext(data);
System.out.println("I should be here, onLoadFinished");
break;
}
} else {
mObjectiveObserver.onError("No data available");
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
if (subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
}
.
In mente che strutturato come questo, in caso di nessun dato chiuderà effettivamente l'abbonamento (OnError lo fa) in modo da non poter ricevere altri dati dal caricatore. Se non lo vuoi, allora in caso di OnError sopra, chiameresti effettivamente onnext con Null o New ArrayList e poi prenditi cura di esso nel tuo osservatore.