2017-10-14 1 views
0

Ich muss zwischengespeicherte Version der Daten aus der Datenbank laden und gleichzeitig möchte ich eine Anfrage an den Server für frische Daten, und ich möchte dies auf einer Seite zu tun. So, zum Beispiel für die erste Seite möchte ich eine im Cache gespeicherte Version der ersten Seite Daten aus der Datenbank zeigen, während neue Daten nur für die erste Seite anfordern.
Ich möchte dies unter Verwendung Paging Library erreichen. Ich versuchte, benutzerdefinierte Datenquelle zu erstellen, die mir half, Seitenladeanforderung abzufangen, die ich dann einen Netzwerkaufruf mit erforderlicher Seitennummer und Limit machte, und inzwischen gab ich eine zwischengespeicherte Version von db zurück, das Problem ist nach dem Erhalten neuer Daten aus dem Netzwerk Ich aktualisiere die Datenbank, aber diese Aktualisierungen werden nicht wiedergegeben. (Ich glaube, die ganze Tabelle wird für alle Änderungen mit Invalidation Tracker beobachtet und Datenquelle wird ungültig, wenn Tabellen ungültig sind, habe ich diesen Tracker in meiner Datenquelle auch hinzugefügt, aber es funktioniert immer noch nicht, ich konnte machen darauf hin, dass Sache Invalidation Tracker vorübergehend zu erstellen: LivePagedListProvider getJobs() in Jobdao und Überprüfung erzeugt Implementierung)Paging-Bibliothek - füllen Sie aus dem Cache während der Anfrage aus dem Netzwerk

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; 
} 
} 

Jobs Repository Funktionen:

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); 
} 

Antwort

0

Also habe ich verstanden, warum es nicht funktionierte, es gab einen Fehler an meinem Ende, ich habe falsche Parameter übergeben, um JobShoo Methode von JobDao in JobsRepository zu bekommen.

Die getJobs Methode der Jobdao geht wie folgt:

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

und der Anruf getJobs() in JobsRepository geht wie folgt:

return mJobDao.getJobs(startPosition, count); 

So ist der erste Parameter war die Grenze und die nächste war der Offset, aber ich ging anders herum.
Jetzt funktioniert es wie ein Charme!

Darüber hinaus habe ich eine Änderung an getJobs() in JobsRepository: Zuerst Daten aus db, wenn verfügbar zurückgeben und eine asynchrone Anfrage an das Netzwerk, falls erforderlich. Wenn keine Daten in db verfügbar sind, machen Sie einen synchronen Aufruf an das Netzwerk, holen Sie Daten aus dem Netzwerk, analysieren Sie es und speichern Sie es db und greifen Sie nun auf die neuesten Daten von db und geben Sie es zurück. So geht die Funktion wie folgt aus:

//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(); 
    } 
} 

(I umbenannt auch die getJobs() in Jobdao zu getJobsLimitOffset(), wie sie es besser lesbar macht, und das ist auch die Art, wie Methoden durch Paging-Bibliothek erzeugt werden)

Verwandte Themen