Skip to content

Commit

Permalink
Add user cache
Browse files Browse the repository at this point in the history
Users that were loaded from the network are now kept in a cache and only
discarded when the app is closed. This means, that if a user navigates
away from the map and then comes back to it no more loading needs to be
done for the previously loaded areas.
Also, the loading is area aware. That means that for overlapping areas
requests are now only made for the non-loaded parts.

Fixes: #101
  • Loading branch information
saemy committed Aug 29, 2018
1 parent c560ce2 commit 159062b
Show file tree
Hide file tree
Showing 4 changed files with 870 additions and 14 deletions.
36 changes: 22 additions & 14 deletions app/src/main/java/fi/bitrite/android/ws/ui/MapFragment.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
Expand Down Expand Up @@ -64,14 +65,14 @@
import fi.bitrite.android.ws.repository.FavoriteRepository;
import fi.bitrite.android.ws.repository.Resource;
import fi.bitrite.android.ws.repository.SettingsRepository;
import fi.bitrite.android.ws.repository.UserRepository;
import fi.bitrite.android.ws.ui.listadapter.UserListAdapter;
import fi.bitrite.android.ws.ui.util.NavigationController;
import fi.bitrite.android.ws.ui.util.UserMarker;
import fi.bitrite.android.ws.ui.util.UserMarkerClusterer;
import fi.bitrite.android.ws.util.LocationManager;
import fi.bitrite.android.ws.util.LoggedInUserHelper;
import fi.bitrite.android.ws.util.Tools;
import fi.bitrite.android.ws.util.UserRegionalCache;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
Expand All @@ -83,7 +84,7 @@ public class MapFragment extends BaseFragment {
private static final String TAG = "MapFragment";

@Inject LoggedInUserHelper mLoggedInUserHelper;
@Inject UserRepository mUserRepository;
@Inject UserRegionalCache mUserRegionalCache;
@Inject FavoriteRepository mFavoriteRepository;
@Inject SettingsRepository mSettingsRepository;

Expand Down Expand Up @@ -163,8 +164,6 @@ public void onCreate(Bundle savedInstanceState) {
mMarkerClusterer.setSingleLocationMarkerFactory(singleLocationMarkerFactory);
mMarkerClusterer.setMultiLocationMarkerFactory(multiLocationMarkerFactory);
mMarkerClusterer.setOnClusterClickListener(this::onClusterClick);

loadOfflineUsers();
}

@Nullable
Expand Down Expand Up @@ -229,6 +228,9 @@ public boolean onZoom(ZoomEvent event) {
doInitialMapMove();
});

loadOfflineUsers();
loadCachedUsers();

return view;
}

Expand Down Expand Up @@ -440,10 +442,12 @@ private void fetchUsersForCurrentMapPosition() {
if (mLastPosition.zoom < getResources().getInteger(R.integer.map_zoom_min_load)) {
sendMessage(R.string.users_dont_load);
} else {
sendMessage(R.string.loading_users);
Handler handler = new Handler();
Runnable r = () -> sendMessage(R.string.loading_users);
handler.postDelayed(r, 500);

getResumePauseDisposable().add(
mUserRepository.searchByLocation(mMap.getBoundingBox())
mUserRegionalCache.searchByLocation(mMap.getBoundingBox())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(searchResult -> {
if (searchResult.isEmpty()) {
Expand All @@ -456,9 +460,10 @@ private void fetchUsersForCurrentMapPosition() {
mMarkerClusterer.invalidate();
mMap.invalidate();
}, throwable -> {
handler.removeCallbacks(r);
// TODO(saemy): Error handling.
Log.e(TAG, throwable.getMessage());
}));
}, () -> handler.removeCallbacks(r)));
}

}
Expand All @@ -468,21 +473,24 @@ private void loadOfflineUsers() {
mLoadOfflineUserDisposable = Observable.merge(mFavoriteRepository.getFavorites())
.filter(Resource::hasData)
.map(userResource -> userResource.data)
// Users pop up twice as one is the error since we might not be able to load it
// from the network.
.filter(user -> mOfflineUserIds.add(user.id))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(user -> {
// Users pop up twice as one is the error since we might not be able to load it
// from the network.
boolean added = mOfflineUserIds.add(user.id);
if (!added) {
return;
}

addUserToCluster(user);
mMarkerClusterer.invalidate();
});
getCreateDestroyDisposable().add(mLoadOfflineUserDisposable);
}

private void loadCachedUsers() {
for (UserSearchByLocationResponse.User user : mUserRegionalCache.getAllCached()) {
addUserToCluster(user.toSimpleUser());
}
mMarkerClusterer.invalidate();
}

private void addUserToCluster(SimpleUser user) {
// Only add to the cluster if it wasn't before or when its location changed.
final Marker existingMarker = mClusteredUsers.get(user.id);
Expand Down
Loading

0 comments on commit 159062b

Please sign in to comment.