I am working with API and Room to get list of Service Technician.
I want to do the following:
- Query to
getAll()
from the Service Technician database table. - Display results to users instantly.
- If it is empty or fails to get database results, make API call to get the same list.
- Make an API call to get updated list of Service Technician.
- Save them into a database table.
- Refresh UI changes based on the latest database content.
Here is what I have, and it works. But I think that it can be improved:
- This looks like not needed call, if I could use somehow Flowable
.flatMap(ids -> techniciansDbRepository.getServiceTechnicians())
- I can not use Flowable since
filter(ServiceTechnician::isActive).toList();
never completes and I do not get result insubscribe()
.
public void getServiceTechnicians() {
disposables = RxUtil.initDisposables(disposables);
Disposable disposable = techniciansDbRepository.getServiceTechnicians()
.subscribeOn(Schedulers.io())
.onErrorResumeNext(throwable -> techniciansApiRepository.getServiceTechnicians())
.flatMap(serviceTechnicians -> techniciansApiRepository.getServiceTechnicians())
.flatMap(techniciansDbRepository::insertAll)
.flatMap(ids -> techniciansDbRepository.getServiceTechnicians())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
serviceTechnicians -> view.onServiceTechniciansLoaded(serviceTechnicians),
view::handleError
);
disposables.add(disposable);
}
public class ServiceTechniciansDbRepository implements ServiceTechniciansRepository {
private final ServiceTechnicianDao dao;
public ServiceTechniciansDbRepository(ServiceTechnicianDao dao) {
this.dao = dao;
}
@Override public Single<List<ServiceTechnician>> getServiceTechnicians() {
return dao.getAll()
.flatMapPublisher(Flowable::fromIterable)
.map(serviceTechnicianAndUser -> ServiceTechnicianMapper.convertToApiModel(
serviceTechnicianAndUser.getServiceTechnician(),
serviceTechnicianAndUser
))
.filter(ServiceTechnician::isActive)
.toList();
}
}
@Dao public abstract class ServiceTechnicianDao implements BaseDao<ServiceTechnicianDb> {
@Transaction
@Query("SELECT * FROM service_technician")
public abstract Single<List<ServiceTechnicianAndUser>> getAll();
@Insert(onConflict = OnConflictStrategy.REPLACE)
public abstract void insertUser(UserDb user);
}
public interface BaseDao<E> {
@Insert(onConflict = OnConflictStrategy.REPLACE)
Single<Long> insert(E e);
@Insert(onConflict = OnConflictStrategy.REPLACE)
Single<List<Long>> insert(List<E> list);
@Update Single<Integer> update(E e);
@Delete Single<Integer> delete(E e);
}
public class ServiceTechniciansApiRepository implements ServiceTechniciansRepository {
private final ServiceTechnicianApi api;
public ServiceTechniciansApiRepository(ServiceTechnicianApi api) {
this.api = api;
}
@Override public Single<List<ServiceTechnician>> getServiceTechnicians() {
return api.getServiceTechnicians()
.subscribeOn(Schedulers.io());
}
@Override public Single<List<Long>> insertAll(List<ServiceTechnician> serviceTechnicians) {
return Single.error(new CanNotBeUsedWithApiException());
}
}
Any idea of how I could improve more this code?