2017-10-14 9 views
0

Je dois charger la version mise en cache des données de la base de données et simultanément je veux faire une requête au serveur pour de nouvelles données et je veux le faire par page. Donc, par exemple pour la première page je veux montrer une version mise en cache des données de première page de la base de données tout en demandant des données fraîches seulement pour la première page.
Je veux atteindre cet objectif en utilisant Paging Library. J'ai essayé de créer une source de données personnalisée qui m'a aidé à intercepter la demande de chargement de page. Ensuite, je faisais un appel réseau avec le numéro de page et la limite requis et je retournais une version mise en cache de DB. Je mets à jour la base de données mais ces mises à jour ne sont pas reflétées. (Je crois que tout le tableau est observé pour toutes les modifications utilisant Invalidation Tracker et la source de données est invalidée chaque fois que les tables sont invalidées, j'ai ajouté ce tracker dans ma source de données mais il ne fonctionne toujours pas, j'ai pu faire que invalidation Tracker chose en créant temporairement: LivePagedListProvider getJobs() dans Jobdao et vérifier la mise en œuvre générée)Bibliothèque de pagination - remplir à partir du cache lors de la demande du réseau

code:

public class JobListDataSource<T> extends TiledDataSource<T> { 

private final JobsRepository mJobsRepository; 
private final InvalidationTracker.Observer mObserver; 


String query = ""; 

public JobListDataSource(JobsRepository jobsRepository) { 
    mJobsRepository = jobsRepository; 

    mObserver = new InvalidationTracker.Observer(JobEntity.TABLE_NAME) { 
     @Override 
     public void onInvalidated(@NonNull Set<String> tables) { 
      invalidate(); 
     } 
    }; 

    jobsRepository.addInvalidationTracker(mObserver); 
} 


@Override 
public int countItems() { 
    return DataSource.COUNT_UNDEFINED; 
} 

@Override 
public List<T> loadRange(int startPosition, int count) { 
    return (List<T>) mJobsRepository.getJobs(query, startPosition, count); 
} 


public void setQuery(String query) { 
    this.query = query; 
} 
} 

fonctions du référentiel Emploi:

public List<JobEntity> getJobs(String query, int startPosition, int count) { 
    if (!isJobListInit) { 
     JobList jobList = mApiService.getOpenJobList(
       mRequestJobList.setPageNo(startPosition/count + 1) 
       .setMaxResults(count) 
       .setSearchKeyword(query) 
     ).blockingSingle(); 
     mJobDao.insert(jobList.getJobsData()); 
    } 
    return mJobDao.getJobs(startPosition, count); 
} 

public void addInvalidationTracker(InvalidationTracker.Observer observer) { 
    mAppDatabase.getInvalidationTracker().addObserver(observer); 
} 

Répondre

0

Alors j'ai compris pourquoi ça ne fonctionnait pas, il y avait une erreur de ma part, je passais de mauvais paramètres à la méthode getJobs de JobDao dans JobsRepository.

La méthode getJobs de Jobdao va comme suit:

@Query("SELECT * FROM jobs ORDER BY jobID ASC LIMIT :limit OFFSET :offset") 
List<JobEntity> getJobs(int limit, int offset); 

Et les getJobs d'appel() en JobsRepository se présente comme suit:

return mJobDao.getJobs(startPosition, count); 

Ainsi, le premier paramètre est la limite et la suivante était le décalage mais je passais d'un autre côté.
Maintenant, cela fonctionne comme un charme!

En outre, j'ai fait un changement à getJobs() dans JobsRepository: D'abord obtenir des données de DB, si disponible retour et faire une demande asynchrone au réseau si nécessaire. Si aucune donnée n'est disponible en db, effectuez un appel synchrone sur le réseau, récupérez les données du réseau, analysez-le et enregistrez-le db et accédez maintenant aux dernières données de db et renvoyez-le. Ainsi, la fonction va comme ceci:

//you can even refactor this code so that all the network related stuff is in one class and just call that method 
public List<JobListItemEntity> getJobs(String query, int startPosition, int count) { 
    Observable<JobList> jobListObservable = mApiService.getOpenJobList(
      mRequestJobList.setPageNo(startPosition/count + 1) 
        .setMaxResults(count) 
        .setSearchKeyword(query)); 

    List<JobListItemEntity> jobs = mJobDao.getJobsLimitOffset(count, startPosition); 

    //no data in db, make a synchronous call to network to get the data 
    if (jobs.size() == 0) { 
     JobList jobList = jobListObservable.blockingSingle(); 
     updateJobList(jobList, startPosition, false); 
    } else if (shouldFetchJobList(jobs)) { 
     //data available in db, so show a cached version and make async network call to update data as this data is no longer fresh 
     jobListObservable.subscribe(new Observer<JobList>() { 
      @Override 
      public void onSubscribe(Disposable d) { 

      } 

      @Override 
      public void onNext(JobList jobList) { 
       updateJobList(jobList, startPosition, true); 
      } 

      @Override 
      public void onError(Throwable e) { 
       Timber.e(e); 
      } 

      @Override 
      public void onComplete() { 

      } 
     }); 
    } 
    return mJobDao.getJobsLimitOffset(count, startPosition); 
} 

updateJobList() Code:

private void updateJobList(JobList jobList, int startPosition, boolean performInvalidation) { 
    JobListItemEntity[] jobs = jobList.getJobsData(); 

    Date currentDate = Calendar.getInstance().getTime(); 

    //tracks when this item was inserted in db, used in calculating whether data is stale 
    for (int i = 0; i < jobs.length; i++) { 
     jobs[i].insertedAt = currentDate; 
    } 

    mJobDao.insert(jobs); 

    if (performInvalidation) { 
     mJobListDataSource.invalidate(); 
    } 
} 

(je aussi Rebaptisé getJobs() dans Jobdao à getJobsLimitOffset() comme il le rend plus lisible et est aussi la façon dont les méthodes sont générées par la bibliothèque de pagination)