mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-31 23:03:54 +01:00
Implemented caching of places
This commit is contained in:
parent
a11003a2fb
commit
411ef31c5e
9 changed files with 206 additions and 43 deletions
|
|
@ -6,6 +6,8 @@ import androidx.room.TypeConverters
|
|||
import fr.free.nrw.commons.contributions.Contribution
|
||||
import fr.free.nrw.commons.contributions.ContributionDao
|
||||
import fr.free.nrw.commons.customselector.database.*
|
||||
import fr.free.nrw.commons.nearby.Place
|
||||
import fr.free.nrw.commons.nearby.PlaceDao
|
||||
import fr.free.nrw.commons.review.ReviewDao
|
||||
import fr.free.nrw.commons.review.ReviewEntity
|
||||
import fr.free.nrw.commons.upload.depicts.Depicts
|
||||
|
|
@ -15,10 +17,11 @@ import fr.free.nrw.commons.upload.depicts.DepictsDao
|
|||
* The database for accessing the respective DAOs
|
||||
*
|
||||
*/
|
||||
@Database(entities = [Contribution::class, Depicts::class, UploadedStatus::class, NotForUploadStatus::class, ReviewEntity::class], version = 16, exportSchema = false)
|
||||
@Database(entities = [Contribution::class, Depicts::class, UploadedStatus::class, NotForUploadStatus::class, ReviewEntity::class, Place::class], version = 18, exportSchema = false)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun contributionDao(): ContributionDao
|
||||
abstract fun PlaceDao(): PlaceDao
|
||||
abstract fun DepictsDao(): DepictsDao;
|
||||
abstract fun UploadedStatusDao(): UploadedStatusDao;
|
||||
abstract fun NotForUploadStatusDao(): NotForUploadStatusDao
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ import fr.free.nrw.commons.CommonsApplication;
|
|||
import fr.free.nrw.commons.contributions.ChunkInfo;
|
||||
import fr.free.nrw.commons.di.ApplicationlessInjection;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.nearby.Sitelinks;
|
||||
import fr.free.nrw.commons.upload.WikidataPlace;
|
||||
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -134,6 +136,18 @@ public class Converters {
|
|||
return readObjectWithTypeToken(depictedItems, new TypeToken<List<DepictedItem>>() {});
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static Sitelinks sitelinksFromString(String value) {
|
||||
Type type = new TypeToken<Sitelinks>() {}.getType();
|
||||
return new Gson().fromJson(value, type);
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static String fromSitelinks(Sitelinks sitelinks) {
|
||||
Gson gson = new Gson();
|
||||
return gson.toJson(sitelinks);
|
||||
}
|
||||
|
||||
private static String writeObjectToString(Object object) {
|
||||
return object == null ? null : getGson().toJson(object);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import fr.free.nrw.commons.data.DBOpenHelper;
|
|||
import fr.free.nrw.commons.db.AppDatabase;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager;
|
||||
import fr.free.nrw.commons.nearby.PlaceDao;
|
||||
import fr.free.nrw.commons.review.ReviewDao;
|
||||
import fr.free.nrw.commons.settings.Prefs;
|
||||
import fr.free.nrw.commons.upload.UploadController;
|
||||
|
|
@ -275,6 +276,11 @@ public class CommonsApplicationModule {
|
|||
return appDatabase.contributionDao();
|
||||
}
|
||||
|
||||
@Provides
|
||||
public PlaceDao providesPlaceDao(AppDatabase appDatabase) {
|
||||
return appDatabase.PlaceDao();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reference of DepictsDao class.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ package fr.free.nrw.commons.nearby;
|
|||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.PrimaryKey;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.nearby.model.NearbyResultItem;
|
||||
import fr.free.nrw.commons.utils.LocationUtils;
|
||||
|
|
@ -14,21 +17,23 @@ import timber.log.Timber;
|
|||
/**
|
||||
* A single geolocated Wikidata item
|
||||
*/
|
||||
@Entity(tableName = "place")
|
||||
public class Place implements Parcelable {
|
||||
|
||||
public final String language;
|
||||
public final String name;
|
||||
private final Label label;
|
||||
private final String longDescription;
|
||||
public String language;
|
||||
public String name;
|
||||
private Label label;
|
||||
private String longDescription;
|
||||
@PrimaryKey @NonNull
|
||||
public LatLng location;
|
||||
private final String category;
|
||||
public final String pic;
|
||||
private String category;
|
||||
public String pic;
|
||||
// exists boolean will tell whether the place exists or not,
|
||||
// For a place to be existing both destroyed and endTime property should be null but it is also not necessary for a non-existing place to have both properties either one property is enough (in such case that not given property will be considered as null).
|
||||
public final Boolean exists;
|
||||
public Boolean exists;
|
||||
|
||||
public String distance;
|
||||
public final Sitelinks siteLinks;
|
||||
public Sitelinks siteLinks;
|
||||
private boolean isMonument;
|
||||
private String thumb;
|
||||
|
||||
|
|
@ -332,4 +337,16 @@ public class Place implements Parcelable {
|
|||
public void setThumb(String thumb) {
|
||||
this.thumb = thumb;
|
||||
}
|
||||
|
||||
public void setLabel(Label label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public void setLongDescription(String longDescription) {
|
||||
this.longDescription = longDescription;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
24
app/src/main/java/fr/free/nrw/commons/nearby/PlaceDao.java
Normal file
24
app/src/main/java/fr/free/nrw/commons/nearby/PlaceDao.java
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
package fr.free.nrw.commons.nearby;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.OnConflictStrategy;
|
||||
import androidx.room.Query;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import io.reactivex.Completable;
|
||||
|
||||
@Dao
|
||||
public abstract class PlaceDao {
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
public abstract void saveSynchronous(Place place);
|
||||
|
||||
@Query("SELECT * from place WHERE location=:l")
|
||||
public abstract Place getPlace(LatLng l);
|
||||
|
||||
public Completable save(final Place place) {
|
||||
return Completable
|
||||
.fromAction(() -> {
|
||||
saveSynchronous(place);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package fr.free.nrw.commons.nearby;
|
||||
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import io.reactivex.Completable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class PlacesLocalDataSource {
|
||||
|
||||
private final PlaceDao placeDao;
|
||||
|
||||
@Inject
|
||||
public PlacesLocalDataSource(
|
||||
final PlaceDao placeDao) {
|
||||
this.placeDao = placeDao;
|
||||
}
|
||||
|
||||
public Place fetchPlace(LatLng latLng){
|
||||
return placeDao.getPlace(latLng);
|
||||
}
|
||||
|
||||
public Completable savePlace(Place place) {
|
||||
return placeDao.save(place);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package fr.free.nrw.commons.nearby;
|
||||
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import io.reactivex.Completable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class PlacesRepository {
|
||||
|
||||
private PlacesLocalDataSource localDataSource;
|
||||
|
||||
@Inject
|
||||
public PlacesRepository(PlacesLocalDataSource localDataSource) {
|
||||
this.localDataSource = localDataSource;
|
||||
}
|
||||
|
||||
public Completable save(Place place){
|
||||
return localDataSource.savePlace(place);
|
||||
}
|
||||
|
||||
public Place fetchPlace(LatLng latLng){
|
||||
return localDataSource.fetchPlace(latLng);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -86,6 +86,7 @@ import fr.free.nrw.commons.nearby.NearbyController;
|
|||
import fr.free.nrw.commons.nearby.NearbyFilterSearchRecyclerViewAdapter;
|
||||
import fr.free.nrw.commons.nearby.NearbyFilterState;
|
||||
import fr.free.nrw.commons.nearby.Place;
|
||||
import fr.free.nrw.commons.nearby.PlacesRepository;
|
||||
import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract;
|
||||
import fr.free.nrw.commons.nearby.fragments.AdvanceQueryFragment.Callback;
|
||||
import fr.free.nrw.commons.nearby.presenter.NearbyParentFragmentPresenter;
|
||||
|
|
@ -99,7 +100,6 @@ import fr.free.nrw.commons.utils.NetworkUtils;
|
|||
import fr.free.nrw.commons.utils.SystemThemeUtils;
|
||||
import fr.free.nrw.commons.utils.ViewUtil;
|
||||
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||
import fr.free.nrw.commons.wikidata.WikidataEditListener.WikidataP18EditListener;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
|
@ -107,14 +107,12 @@ import io.reactivex.schedulers.Schedulers;
|
|||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
|
@ -160,6 +158,8 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
@Inject
|
||||
BookmarkLocationsDao bookmarkLocationDao;
|
||||
@Inject
|
||||
PlacesRepository placesRepository;
|
||||
@Inject
|
||||
ContributionController controller;
|
||||
@Inject
|
||||
WikidataEditListener wikidataEditListener;
|
||||
|
|
@ -1244,6 +1244,7 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
Place pl = updatedPlaceList.get(i);
|
||||
if (pl.location == updatedPlace.location){
|
||||
updatedPlaceList.set(i, updatedPlace);
|
||||
savePlaceToDB(place);
|
||||
}
|
||||
}
|
||||
Drawable icon = ContextCompat.getDrawable(getContext(), getIconFor(updatedPlace, isBookMarked));
|
||||
|
|
@ -1381,13 +1382,13 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
if (stopQuery) {
|
||||
return;
|
||||
}
|
||||
if (!p.isEmpty()) {
|
||||
if (!p.isEmpty() && p != updatedPlaceList) {
|
||||
synchronized (updatedPlaceList) {
|
||||
updatedPlaceList.clear();
|
||||
updatedPlaceList.addAll((Collection<? extends Place>) p);
|
||||
}
|
||||
updateMapMarkers(new ArrayList<>(updatedPlaceList), curLatLng, false);
|
||||
}
|
||||
updateMapMarkers(new ArrayList<>(updatedPlaceList), curLatLng, false);
|
||||
processBatchesSequentially(places, batchSize, updatedPlaceList, curLatLng, endIndex);
|
||||
}, throwable -> {
|
||||
Timber.e(throwable);
|
||||
|
|
@ -1399,7 +1400,41 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
}
|
||||
|
||||
private Observable<List<?>> processBatch(List<Place> batch, List<Place> placeList) {
|
||||
return Observable.fromCallable(() -> nearbyController.getPlaces(batch))
|
||||
List<Place> toBeProcessed = new ArrayList<>();
|
||||
|
||||
List<Observable<Place>> placeObservables = new ArrayList<>();
|
||||
|
||||
for (Place place : batch) {
|
||||
Observable<Place> placeObservable = Observable
|
||||
.fromCallable(() -> {
|
||||
Place fetchedPlace = placesRepository.fetchPlace(place.location);
|
||||
return fetchedPlace != null ? fetchedPlace : place;
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext(placeData -> {
|
||||
if (placeData.equals(place)) {
|
||||
toBeProcessed.add(place);
|
||||
} else {
|
||||
for (int i = 0; i < placeList.size(); i++) {
|
||||
Place pl = placeList.get(i);
|
||||
if (pl.location.equals(place.location)) {
|
||||
placeList.set(i, placeData);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
placeObservables.add(placeObservable);
|
||||
}
|
||||
|
||||
return Observable.zip(placeObservables, objects -> toBeProcessed)
|
||||
.flatMap(processedList -> {
|
||||
if (processedList.isEmpty()) {
|
||||
return Observable.just(placeList);
|
||||
}
|
||||
return Observable.fromCallable(() -> nearbyController.getPlaces(processedList))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.map(places -> {
|
||||
|
|
@ -1407,19 +1442,20 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
return Collections.emptyList();
|
||||
}
|
||||
if (places == null || places.isEmpty()) {
|
||||
showErrorMessage(getString(R.string.no_nearby_places_around));
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
List<Place> updatedPlaceList = new ArrayList<>(placeList);
|
||||
for (Place place : places) {
|
||||
for (Place foundPlace : placeList) {
|
||||
if (place.siteLinks.getWikidataLink().equals(foundPlace.siteLinks.getWikidataLink())) {
|
||||
if (place.siteLinks.getWikidataLink()
|
||||
.equals(foundPlace.siteLinks.getWikidataLink())) {
|
||||
place.location = foundPlace.location;
|
||||
place.distance = foundPlace.distance;
|
||||
place.setMonument(foundPlace.isMonument());
|
||||
int index = updatedPlaceList.indexOf(foundPlace);
|
||||
if (index != -1) {
|
||||
updatedPlaceList.set(index, place);
|
||||
savePlaceToDB(place);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1430,10 +1466,19 @@ public class NearbyParentFragment extends CommonsDaggerSupportFragment
|
|||
})
|
||||
.onErrorReturn(throwable -> {
|
||||
Timber.e(throwable);
|
||||
showErrorMessage(getString(R.string.error_fetching_nearby_places) + " " + throwable.getLocalizedMessage());
|
||||
showErrorMessage(getString(R.string.error_fetching_nearby_places) + " "
|
||||
+ throwable.getLocalizedMessage());
|
||||
setFilterState();
|
||||
return Collections.emptyList();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void savePlaceToDB(Place place) {
|
||||
compositeDisposable.add(placesRepository
|
||||
.save(place)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -14,8 +14,10 @@ import android.location.Location;
|
|||
import android.view.View;
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.work.ExistingWorkPolicy;
|
||||
import fr.free.nrw.commons.BaseMarker;
|
||||
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsDao;
|
||||
import fr.free.nrw.commons.contributions.Contribution;
|
||||
import fr.free.nrw.commons.kvstore.JsonKvStore;
|
||||
import fr.free.nrw.commons.location.LatLng;
|
||||
import fr.free.nrw.commons.location.LocationServiceManager.LocationChangeType;
|
||||
|
|
@ -26,9 +28,12 @@ import fr.free.nrw.commons.nearby.MarkerPlaceGroup;
|
|||
import fr.free.nrw.commons.nearby.NearbyController;
|
||||
import fr.free.nrw.commons.nearby.NearbyFilterState;
|
||||
import fr.free.nrw.commons.nearby.Place;
|
||||
import fr.free.nrw.commons.nearby.PlaceDao;
|
||||
import fr.free.nrw.commons.nearby.contract.NearbyParentFragmentContract;
|
||||
import fr.free.nrw.commons.upload.worker.WorkRequestHelper;
|
||||
import fr.free.nrw.commons.utils.LocationUtils;
|
||||
import fr.free.nrw.commons.wikidata.WikidataEditListener;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.List;
|
||||
import timber.log.Timber;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue