feat: consider event ID to load single event and only more when requested by user

This commit is contained in:
Robert Benedikt committed 2020-12-01 11:40:13 +01:00
1 parent 596ac69a93
commit fcfc7d535b
17 files changed
+295 -205

No files matched your search

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminate="true" />
</FrameLayout>
@@ -1,16 +1,7 @@
package com.sap.sailing.racecommittee.app.data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
import android.content.Context;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor;
import com.sap.sailing.domain.abstractlog.race.RaceLog;
@@ -57,8 +48,17 @@ import com.sap.sse.common.Color;
import com.sap.sse.common.TimePoint;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import android.content.Context;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;
public class OfflineDataManager extends DataManager {
@@ -82,13 +82,13 @@ public class OfflineDataManager extends DataManager {
final TimePoint endDate = new MillisecondsTimePoint(cal.getTimeInMillis());
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Cardiff)", startDate, endDate, "Cardiff",
true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet(), Collections.emptySet()));
true, UUID.randomUUID(), Collections.<LeaderboardGroupBase>emptySet(), Collections.emptySet()));
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Nice)", startDate, endDate, "Nice", true,
UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet(), Collections.emptySet()));
UUID.randomUUID(), Collections.<LeaderboardGroupBase>emptySet(), Collections.emptySet()));
dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Rio)", startDate, endDate, "Rio", true,
UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet(), Collections.emptySet()));
UUID.randomUUID(), Collections.<LeaderboardGroupBase>emptySet(), Collections.emptySet()));
EventBase newEvent = new StrippedEventImpl("Extreme Sailing Series 2013 (Muscat)", startDate, endDate, "Muscat",
true, UUID.randomUUID(), Collections.<LeaderboardGroupBase> emptySet(), Collections.emptySet());
true, UUID.randomUUID(), Collections.<LeaderboardGroupBase>emptySet(), Collections.emptySet());
final CourseAreaImpl offshore = new CourseAreaImpl("Offshore", UUID.randomUUID());
newEvent.getVenue().addCourseArea(offshore);
final CourseAreaImpl stadium = new CourseAreaImpl("Stadium", UUID.randomUUID());
@@ -165,14 +165,19 @@ public class OfflineDataManager extends DataManager {
@Override
public LoaderCallbacks<DataLoaderResult<Collection<EventBase>>> createEventsLoader(
LoadClient<Collection<EventBase>> callback) {
return new ImmediateDataLoaderCallbacks<Collection<EventBase>>(context, callback,
new Callable<Collection<EventBase>>() {
@Override
public Collection<EventBase> call() throws Exception {
return dataStore.getEvents();
}
});
LoadClient<Collection<EventBase>> callback,
UUID... eventIds
) {
return new ImmediateDataLoaderCallbacks<>(context, callback, () -> {
if (eventIds.length == 0) {
return dataStore.getEvents();
}
final List<EventBase> events = new ArrayList<>();
for (UUID eventId : eventIds) {
events.add(dataStore.getEvent(eventId));
}
return events;
});
}
@Override
@@ -201,8 +206,10 @@ public class OfflineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<ManagedRace>>> createRacesLoader(Serializable courseAreaId,
LoadClient<Collection<ManagedRace>> callback) {
public LoaderCallbacks<DataLoaderResult<Collection<ManagedRace>>> createRacesLoader(
Serializable courseAreaId,
LoadClient<Collection<ManagedRace>> callback
) {
return new ImmediateDataLoaderCallbacks<Collection<ManagedRace>>(context, callback,
new Callable<Collection<ManagedRace>>() {
@Override
@@ -213,8 +220,10 @@ public class OfflineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<Mark>>> createMarksLoader(ManagedRace managedRace,
LoadClient<Collection<Mark>> callback) {
public LoaderCallbacks<DataLoaderResult<Collection<Mark>>> createMarksLoader(
ManagedRace managedRace,
LoadClient<Collection<Mark>> callback
) {
return new ImmediateDataLoaderCallbacks<Collection<Mark>>(context, callback, new Callable<Collection<Mark>>() {
@Override
public Collection<Mark> call() throws Exception {
@@ -224,8 +233,10 @@ public class OfflineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<CourseBase>> createCourseLoader(final ManagedRace managedRace,
LoadClient<CourseBase> callback) {
public LoaderCallbacks<DataLoaderResult<CourseBase>> createCourseLoader(
final ManagedRace managedRace,
LoadClient<CourseBase> callback
) {
return new ImmediateDataLoaderCallbacks<CourseBase>(context, callback, new Callable<CourseBase>() {
@Override
public CourseBase call() throws Exception {
@@ -259,8 +270,10 @@ public class OfflineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<LeaderboardResult>> createLeaderboardLoader(ManagedRace managedRace,
LoadClient<LeaderboardResult> callback) {
public LoaderCallbacks<DataLoaderResult<LeaderboardResult>> createLeaderboardLoader(
ManagedRace managedRace,
LoadClient<LeaderboardResult> callback
) {
return new ImmediateDataLoaderCallbacks<>(context, callback, new Callable<LeaderboardResult>() {
@Override
public LeaderboardResult call() throws Exception {
@@ -283,7 +296,7 @@ public class OfflineDataManager extends DataManager {
@Override
public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts,
boolean showStreamlets, boolean showSimulation, boolean showMapControls) {
boolean showStreamlets, boolean showSimulation, boolean showMapControls) {
throw new IllegalStateException("No wind map in offline mode.");
}
@@ -71,8 +71,8 @@ import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserial
import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardGroupBaseJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.RaceColumnFactorJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.RegattaConfigurationJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.TrackingConnectorInfoJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer;
import com.sap.sailing.server.gateway.deserialization.racegroup.impl.RaceGroupDeserializer;
import com.sap.sse.common.Util;
@@ -120,24 +120,28 @@ public class OnlineDataManager extends DataManager {
@Override
public LoaderCallbacks<DataLoaderResult<Collection<EventBase>>> createEventsLoader(
LoadClient<Collection<EventBase>> callback) {
return new DataLoaderCallbacks<>(callback, new LoaderCreator<Collection<EventBase>>() {
@Override
public Loader<DataLoaderResult<Collection<EventBase>>> create(int id, Bundle args) throws Exception {
ExLog.i(context, TAG, "Creating Events-OnlineDataLoader " + id);
EventBaseJsonDeserializer serializer = new EventBaseJsonDeserializer(
new VenueJsonDeserializer(new CourseAreaJsonDeserializer(domainFactory)),
new LeaderboardGroupBaseJsonDeserializer(),
new TrackingConnectorInfoJsonDeserializer());
DataParser<Collection<EventBase>> parser = new EventsDataParser(serializer);
DataHandler<Collection<EventBase>> handler = new EventsDataHandler(OnlineDataManager.this);
// ExLog.i(context, TAG, "getEventsLoader created new loader...");
List<Util.Pair<String, Object>> params = new ArrayList<>();
params.add(new Util.Pair<String, Object>("showNonPublic", AppPreferences.on(context).showNonPublic()));
URL url = UrlHelper.generateUrl(preferences.getServerBaseURL(), "/sailingserver/api/v1/events", params);
return new OnlineDataLoader<>(context, url, parser, handler);
LoadClient<Collection<EventBase>> callback,
UUID... eventIds
) {
return new DataLoaderCallbacks<>(callback, (id, args) -> {
ExLog.i(context, TAG, "Creating Events-OnlineDataLoader " + id);
final EventBaseJsonDeserializer serializer = new EventBaseJsonDeserializer(
new VenueJsonDeserializer(new CourseAreaJsonDeserializer(domainFactory)),
new LeaderboardGroupBaseJsonDeserializer(),
new TrackingConnectorInfoJsonDeserializer()
);
final DataParser<Collection<EventBase>> parser = new EventsDataParser(serializer);
final DataHandler<Collection<EventBase>> handler = new EventsDataHandler(OnlineDataManager.this);
final List<Util.Pair<String, Object>> params = new ArrayList<>();
params.add(new Util.Pair<>("showNonPublic", AppPreferences.on(context).showNonPublic()));
if (eventIds.length > 0) {
params.add(new Util.Pair<>("include", true));
for (UUID eventId : eventIds) {
params.add(new Util.Pair<>("id", eventId));
}
}
URL url = UrlHelper.generateUrl(preferences.getServerBaseURL(), "/sailingserver/api/v1/events", params);
return new OnlineDataLoader<>(context, url, parser, handler);
}, getContext());
}
@@ -173,8 +177,10 @@ public class OnlineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<ManagedRace>>> createRacesLoader(final Serializable courseAreaId,
LoadClient<Collection<ManagedRace>> callback) {
public LoaderCallbacks<DataLoaderResult<Collection<ManagedRace>>> createRacesLoader(
final Serializable courseAreaId,
LoadClient<Collection<ManagedRace>> callback
) {
return new DataLoaderCallbacks<>(callback, new LoaderCreator<Collection<ManagedRace>>() {
@Override
public Loader<DataLoaderResult<Collection<ManagedRace>>> create(int id, Bundle args) throws Exception {
@@ -199,8 +205,10 @@ public class OnlineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<Collection<Mark>>> createMarksLoader(final ManagedRace managedRace,
LoadClient<Collection<Mark>> callback) {
public LoaderCallbacks<DataLoaderResult<Collection<Mark>>> createMarksLoader(
final ManagedRace managedRace,
LoadClient<Collection<Mark>> callback
) {
return new DataLoaderCallbacks<>(callback, new LoaderCreator<Collection<Mark>>() {
@Override
public Loader<DataLoaderResult<Collection<Mark>>> create(int id, Bundle args) throws Exception {
@@ -229,8 +237,10 @@ public class OnlineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<CourseBase>> createCourseLoader(final ManagedRace managedRace,
LoadClient<CourseBase> callback) {
public LoaderCallbacks<DataLoaderResult<CourseBase>> createCourseLoader(
final ManagedRace managedRace,
LoadClient<CourseBase> callback
) {
return new DataLoaderCallbacks<>(callback, new LoaderCreator<CourseBase>() {
@Override
public Loader<DataLoaderResult<CourseBase>> create(int id, Bundle args) throws Exception {
@@ -319,8 +329,10 @@ public class OnlineDataManager extends DataManager {
}
@Override
public LoaderCallbacks<DataLoaderResult<LeaderboardResult>> createLeaderboardLoader(final ManagedRace managedRace,
LoadClient<LeaderboardResult> callback) {
public LoaderCallbacks<DataLoaderResult<LeaderboardResult>> createLeaderboardLoader(
final ManagedRace managedRace,
LoadClient<LeaderboardResult> callback
) {
return new DataLoaderCallbacks<>(callback, new LoaderCreator<LeaderboardResult>() {
@Override
public Loader<DataLoaderResult<LeaderboardResult>> create(int id, Bundle args) throws Exception {
@@ -371,7 +383,7 @@ public class OnlineDataManager extends DataManager {
@Override
public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts,
boolean showStreamlets, boolean showSimulation, boolean showMapControls) {
boolean showStreamlets, boolean showSimulation, boolean showMapControls) {
String url = "";
// get simple race log identifier
Util.Triple<String, String, String> triple = FleetIdentifierImpl.unescape(race.getId());
@@ -1,9 +1,7 @@
package com.sap.sailing.racecommittee.app.data;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import com.sap.sailing.domain.base.Boat;
import com.sap.sailing.domain.base.Competitor;
@@ -20,20 +18,22 @@ import com.sap.sailing.racecommittee.app.domain.ManagedRace;
import com.sap.sailing.racecommittee.app.domain.impl.LeaderboardResult;
import com.sap.sailing.racecommittee.app.ui.fragments.lists.PositionListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
/**
* <p>
* Interface for everything read related when working with data.
* </p>
*
*
* <p>
* The result values of this interface's methods are meant to be used in conjunction with the Android's
* {@link LoaderManager} facility. Everything that is loaded by this interface is stored and cached in the underlying
* {@link DataStore}.
* </p>
*
*
* <p>
* If there are cached results your {@link LoadClient}'s callback methods might be called twice (first cached results;
* afterwards remote results). See {@link LoadClient} for restrictions that apply to your data handling code.
@@ -43,144 +43,149 @@ public interface ReadonlyDataManager {
/**
* Gets the underlying data store.
*
*
* @return the {@link DataStore}.
*/
DataStore getDataStore();
/**
* Creates a new {@link LoaderCallbacks} object for loading {@link EventBase}s.
*
* @param callback
* {@link LoadClient} implementing your data handling code.
*
* @param callback {@link LoadClient} implementing your data handling code.
* @param eventIds Event IDs to filter the results.
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<Collection<EventBase>>> createEventsLoader(
LoadClient<Collection<EventBase>> callback);
LoadClient<Collection<EventBase>> callback,
UUID... eventIds
);
/**
* Creates a new {@link LoaderCallbacks} object for loading {@link CourseArea}s.
*
* @param callback
* {@link LoadClient} implementing your data handling code.
*
* @param callback {@link LoadClient} implementing your data handling code.
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<Collection<CourseArea>>> createCourseAreasLoader(Serializable parentEventId,
LoadClient<Collection<CourseArea>> callback);
LoaderCallbacks<DataLoaderResult<Collection<CourseArea>>> createCourseAreasLoader(
Serializable parentEventId,
LoadClient<Collection<CourseArea>> callback
);
LoaderCallbacks<DataLoaderResult<Collection<CourseArea>>> createCourseAreasLoader(EventBase parentEvent,
LoadClient<Collection<CourseArea>> callback);
LoaderCallbacks<DataLoaderResult<Collection<CourseArea>>> createCourseAreasLoader(
EventBase parentEvent,
LoadClient<Collection<CourseArea>> callback
);
/**
* Creates a new {@link LoaderCallbacks} object for loading racing referee positions.
*
*
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<Collection<CoursePosition>>> createPositionLoader(
PositionListFragment positionListFragment);
/**
* Creates a new {@link LoaderCallbacks} object for loading {@link ManagedRace}s of a specific {@link CourseArea}.
*
* @param courseAreaId
* the {@link CourseArea}'s Identifier.
* @param callback
* {@link LoadClient} implementing your data handling code.
*
* @param courseAreaId the {@link CourseArea}'s Identifier.
* @param callback {@link LoadClient} implementing your data handling code.
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<Collection<ManagedRace>>> createRacesLoader(Serializable courseAreaId,
LoadClient<Collection<ManagedRace>> callback);
LoaderCallbacks<DataLoaderResult<Collection<ManagedRace>>> createRacesLoader(
Serializable courseAreaId,
LoadClient<Collection<ManagedRace>> callback
);
/**
* Creates a new {@link LoaderCallbacks} object for loading a race's {@link Mark}s.
*
* @param managedRace
* the {@link ManagedRace}.
* @param callback
* {@link LoadClient} implementing your data handling code.
*
* @param managedRace the {@link ManagedRace}.
* @param callback {@link LoadClient} implementing your data handling code.
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<Collection<Mark>>> createMarksLoader(ManagedRace managedRace,
LoadClient<Collection<Mark>> callback);
LoaderCallbacks<DataLoaderResult<Collection<Mark>>> createMarksLoader(
ManagedRace managedRace,
LoadClient<Collection<Mark>> callback
);
/**
* Creates a new {@link LoaderCallbacks} object for loading a race's {@link CourseBase}.
*
* @param managedRace
* the {@link ManagedRace}.
* @param callback
* {@link LoadClient} implementing your data handling code.
*
* @param managedRace the {@link ManagedRace}.
* @param callback {@link LoadClient} implementing your data handling code.
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<CourseBase>> createCourseLoader(ManagedRace managedRace,
LoadClient<CourseBase> callback);
LoaderCallbacks<DataLoaderResult<CourseBase>> createCourseLoader(
ManagedRace managedRace,
LoadClient<CourseBase> callback
);
/**
* Creates a new {@link LoaderCallbacks} object for loading {@link Competitor}s.
*
* @param callback
* {@link LoadClient} implementing your data handling code.
*
* @param callback {@link LoadClient} implementing your data handling code.
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<Map<Competitor, Boat>>> createCompetitorsLoader(ManagedRace managedRace,
LoadClient<Map<Competitor, Boat>> callback);
LoaderCallbacks<DataLoaderResult<Map<Competitor, Boat>>> createCompetitorsLoader(
ManagedRace managedRace,
LoadClient<Map<Competitor, Boat>> callback
);
/**
* Create a new {@link LoaderCallbacks} object for loading {@link Competitor}
*
* @param callback
* {@link LoadClient} implementing your data handling code.
* @param callback {@link LoadClient} implementing your data handling code.
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<Map<Competitor, Boat>>> createStartOrderLoader(ManagedRace managedRace,
LoadClient<Map<Competitor, Boat>> callback);
LoaderCallbacks<DataLoaderResult<Map<Competitor, Boat>>> createStartOrderLoader(
ManagedRace managedRace,
LoadClient<Map<Competitor, Boat>> callback
);
/**
* Create a new {@link LoaderCallbacks} object for loading {@link LeaderboardResult}
*
* @param managedRace
* the {@link ManagedRace}
* @param callback
* {@link LoadClient} implementing your data handling code
* @param managedRace the {@link ManagedRace}
* @param callback {@link LoadClient} implementing your data handling code
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<LeaderboardResult>> createLeaderboardLoader(ManagedRace managedRace,
LoadClient<LeaderboardResult> callback);
LoaderCallbacks<DataLoaderResult<LeaderboardResult>> createLeaderboardLoader(
ManagedRace managedRace,
LoadClient<LeaderboardResult> callback
);
/**
* Creates a new {@link LoaderCallbacks} object for loading a client's configuration.
*
*
* @param deviceConfigurationUuid
* @param callback
* {@link LoadClient} implementing your data handling code.
* @param callback {@link LoadClient} implementing your data handling code.
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<DeviceConfiguration>> createConfigurationLoader(
String deviceConfigurationName, UUID deviceConfigurationUuid, LoadClient<DeviceConfiguration> callback);
String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, boolean showStreamlets,
boolean showSimulation, boolean showMapControls);
boolean showSimulation, boolean showMapControls);
/**
* Create a new {@link LoaderCallbacks} object for loading the race columns (e.g. factors)
@@ -188,10 +193,9 @@ public interface ReadonlyDataManager {
* @param leaderboard
* @param race_column
* @param callback
*
* @return {@link LoaderCallbacks} to be used in
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
* {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or
* {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}.
*/
LoaderCallbacks<DataLoaderResult<RaceColumnFactorImpl>> createRaceColumnFactorLoader(
LoadClient<RaceColumnFactorImpl> callback);
@@ -6,28 +6,23 @@ import android.support.v4.content.Loader;
/**
* Interface to hide complexity of {@link LoaderCallbacks#onLoadFinished(Loader, Object)}. Keep in mind that all
* restrictions that apply on the LoaderCallback's method also apply to all methods of this interface.
*
* @param <T>
* loaded data type.
*
* @param <T> loaded data type.
*/
public interface LoadClient<T> {
/**
* Called when a {@link Loader} returned a failure to its {@link LoaderCallbacks#onLoadFinished(Loader, Object)}.
*
* @param reason
* the loading has failed.
*
* @param reason the loading has failed.
*/
public void onLoadFailed(Exception reason);
void onLoadFailed(int loaderId, Exception reason);
/**
* Called when a {@link Loader} returned successfully to its {@link LoaderCallbacks#onLoadFinished(Loader, Object)}.
*
* @param data
* that was loaded.
* @param isCached
* <code>true</code> if returned data is cached data.
*
* @param data that was loaded.
* @param isCached <code>true</code> if returned data is cached data.
*/
public void onLoadSucceeded(T data, boolean isCached);
void onLoadSucceeded(int loaderId, T data, boolean isCached);
}
@@ -1,30 +1,29 @@
package com.sap.sailing.racecommittee.app.data.loaders;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.racecommittee.app.data.clients.LoadClient;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import com.sap.sailing.android.shared.logging.ExLog;
import com.sap.sailing.racecommittee.app.data.clients.LoadClient;
/**
* <p>
* {@link LoaderCallbacks} wrapper to be used with {@link LoadClient}s.
* </p>
*
*
* <p>
* On result {@link DataLoaderResult#isSuccessful()} is checked. If true
* {@link LoadClient#onLoadSucceeded(Object, boolean)} is called; other {@link LoadClient#onLoadFailed(Exception)} is
* {@link LoadClient#onLoadSucceeded(int, Object, boolean)} is called; other {@link LoadClient#onLoadFailed(int, Exception)} is
* called.
* </p>
*
*
* <p>
* There is currently no handling of a {@link Loader}'s reset.
* </p>
*
* @param <T>
* result type.
*
* @param <T> result type.
*/
public class DataLoaderCallbacks<T> implements LoaderCallbacks<DataLoaderResult<T>> {
private static String TAG = DataLoaderCallbacks.class.getName();
@@ -57,9 +56,9 @@ public class DataLoaderCallbacks<T> implements LoaderCallbacks<DataLoaderResult<
public void onLoadFinished(Loader<DataLoaderResult<T>> loader, DataLoaderResult<T> result) {
if (result.isSuccessful()) {
clientCallback.onLoadSucceeded(result.getResult(), result.isResultCached());
clientCallback.onLoadSucceeded(loader.getId(), result.getResult(), result.isResultCached());
} else {
clientCallback.onLoadFailed(result.getException());
clientCallback.onLoadFailed(loader.getId(), result.getException());
}
}
@@ -461,7 +461,7 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
LoaderCallbacks<?> configurationLoader = dataManager.createConfigurationLoader(deviceConfigurationName,
deviceConfigurationUuid, new LoadClient<DeviceConfiguration>() {
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
dismissProgressSpinner();
if (reason instanceof FileNotFoundException) {
@@ -479,7 +479,7 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener
}
@Override
public void onLoadSucceeded(DeviceConfiguration configuration, boolean isCached) {
public void onLoadSucceeded(int loaderId, DeviceConfiguration configuration, boolean isCached) {
getSupportLoaderManager().destroyLoader(0);
dismissProgressSpinner();
@@ -677,7 +677,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
}
@Override
public void onLoadFailed(Exception ex) {
public void onLoadFailed(int loaderId, Exception ex) {
setProgressSpinnerVisibility(false);
AlertDialog.Builder builder = new AlertDialog.Builder(RacingActivity.this);
builder.setMessage(String.format(getString(R.string.generic_load_failure), ex.getMessage()))
@@ -694,7 +694,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks
}
@Override
public void onLoadSucceeded(Collection<ManagedRace> data, boolean isCached) {
public void onLoadSucceeded(int loaderId, Collection<ManagedRace> data, boolean isCached) {
// need to be a new instance, because of Activity restart after background kill
// more information see bug 3741
lastSeenRaces = new ArrayList<>(data);
@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.View;
@@ -20,6 +21,7 @@ import com.sap.sailing.android.shared.util.ViewHelper;
import com.sap.sailing.racecommittee.app.AppConstants;
import com.sap.sailing.racecommittee.app.R;
import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.LoggableDialogFragment;
import com.sap.sailing.racecommittee.app.ui.fragments.lists.EventListFragment;
import java.util.ArrayList;
import java.util.List;
@@ -118,7 +120,15 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli
case R.id.event_header:
mCourseAreaContainer.close();
mPositionContainer.close();
mEventContainer.toggle();
final boolean expanded = mEventContainer.toggle();
final Fragment fragment = requireFragmentManager().findFragmentById(R.id.event_fragment);
if (fragment instanceof EventListFragment) {
if (expanded) {
((EventListFragment) fragment).onExpanded();
} else {
((EventListFragment) fragment).onCollapsed();
}
}
break;
case R.id.area_header:
@@ -174,7 +184,7 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli
mAppUtils = AppUtils.with(getActivity());
}
public void toggle() {
public boolean toggle() {
final int[] pos = new int[2];
if (mFrame != null && mFrame.getLayoutParams() != null) {
@@ -194,10 +204,12 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli
mFrame.getLayoutParams().height = ScreenHelper.on(getActivity()).getScreenHeight() - pos[1];
mFrame.requestLayout();
setVisibility(mText, View.GONE);
return true;
} else {
close();
}
}
return false;
}
public void close() {
@@ -79,7 +79,7 @@ public class MainPreferenceFragment extends LoggableFragment {
.createConfigurationLoader(deviceConfigurationName, deviceConfigurationUuid, new LoadClient<DeviceConfiguration>() {
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
if (reason instanceof FileNotFoundException) {
Toast.makeText(getActivity(),
getString(R.string.loading_configuration_not_found),
@@ -96,8 +96,8 @@ public class MainPreferenceFragment extends LoggableFragment {
}
@Override
public void onLoadSucceeded(DeviceConfiguration configuration,
boolean isCached) {
public void onLoadSucceeded(int loaderId, DeviceConfiguration configuration,
boolean isCached) {
getLoaderManager().destroyLoader(0);
// this is our 'global' configuration, let's store it in app preferences
@@ -61,8 +61,8 @@ public class CourseAreaListFragment extends NamedListFragment<CourseArea> {
}
@Override
public void onLoadSucceeded(Collection<CourseArea> data, boolean isCached) {
super.onLoadSucceeded(data, isCached);
public void onLoadSucceeded(int loaderId, Collection<CourseArea> data, boolean isCached) {
super.onLoadSucceeded(loaderId, data, isCached);
for (CheckedItem item : checkedItems) {
item.setDisabled(true);
@@ -4,6 +4,7 @@ import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.text.TextUtils;
import com.sap.sailing.domain.base.EventBase;
@@ -14,6 +15,7 @@ import com.sap.sailing.racecommittee.app.ui.fragments.lists.selection.EventSelec
import com.sap.sailing.racecommittee.app.ui.fragments.lists.selection.ItemSelectedListener;
import java.util.Collection;
import java.util.UUID;
public class EventListFragment extends NamedListFragment<EventBase> {
@@ -41,7 +43,12 @@ public class EventListFragment extends NamedListFragment<EventBase> {
@Override
protected LoaderCallbacks<DataLoaderResult<Collection<EventBase>>> createLoaderCallbacks(
ReadonlyDataManager manager) {
ReadonlyDataManager manager
) {
if (getArguments() != null && getArguments().containsKey(AppConstants.EXTRA_EVENT_ID)) {
final UUID eventId = UUID.fromString(getArguments().getString(AppConstants.EXTRA_EVENT_ID));
return manager.createEventsLoader(this, eventId);
}
return manager.createEventsLoader(this);
}
@@ -51,8 +58,11 @@ public class EventListFragment extends NamedListFragment<EventBase> {
}
@Override
public void onLoadSucceeded(Collection<EventBase> data, boolean isCached) {
super.onLoadSucceeded(data, isCached);
public void onLoadSucceeded(int loaderId, Collection<EventBase> data, boolean isCached) {
if (loaderId == 1 && isCached) {
return;
}
super.onLoadSucceeded(loaderId, data, isCached);
final Bundle arguments = getArguments();
if (arguments != null && mSelectedIndex == -1) {
final String id = arguments.getString(AppConstants.EXTRA_EVENT_ID);
@@ -64,4 +74,32 @@ public class EventListFragment extends NamedListFragment<EventBase> {
}
}
}
@Override
public void onLoadFailed(int loaderId, Exception reason) {
super.onLoadFailed(loaderId, reason);
if (loaderId == 0) {
showProgressBar(false);
}
}
public void onExpanded() {
if (getArguments() != null && getArguments().containsKey(AppConstants.EXTRA_EVENT_ID)) {
showProgressBar(true);
Loader<DataLoaderResult<Collection<EventBase>>> loader = getLoaderManager().getLoader(1);
if (loader == null) {
getLoadMoreLoader().forceLoad();
} else {
getLoadMoreLoader();
}
}
}
private Loader<DataLoaderResult<Collection<EventBase>>> getLoadMoreLoader() {
return getLoaderManager().initLoader(1, null, getDataManager().createEventsLoader(this));
}
public void onCollapsed() {
showProgressBar(false);
}
}
@@ -46,6 +46,7 @@ public abstract class NamedListFragment<T extends Named> extends LoggableListFra
protected ItemSelectedListener<T> listener;
protected CheckedItemAdapter listAdapter;
protected int mSelectedIndex = -1;
private View footerView;
protected abstract ItemSelectedListener<T> attachListener(Activity activity);
@@ -84,6 +85,9 @@ public abstract class NamedListFragment<T extends Named> extends LoggableListFra
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
footerView = View.inflate(requireContext(), R.layout.footer_progress, null);
getListView().addFooterView(footerView);
showProgressBar(true);
loadItems();
}
@@ -100,7 +104,7 @@ public abstract class NamedListFragment<T extends Named> extends LoggableListFra
}
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
namedList.clear();
listAdapter.notifyDataSetChanged();
@@ -122,7 +126,7 @@ public abstract class NamedListFragment<T extends Named> extends LoggableListFra
}
@Override
public void onLoadSucceeded(Collection<T> data, boolean isCached) {
public void onLoadSucceeded(int loaderId, Collection<T> data, boolean isCached) {
namedList.clear();
checkedItems.clear();
if (isForceLoad() && !isCached) {
@@ -183,8 +187,12 @@ public abstract class NamedListFragment<T extends Named> extends LoggableListFra
super.onSaveInstanceState(outState);
}
public Loader<DataLoaderResult<Collection<T>>> getLoader() {
return getLoaderManager().initLoader(0, null, createLoaderCallbacks(OnlineDataManager.create(getActivity())));
ReadonlyDataManager getDataManager() {
return OnlineDataManager.create(getActivity());
}
Loader<DataLoaderResult<Collection<T>>> getLoader() {
return getLoaderManager().initLoader(0, null, createLoaderCallbacks(getDataManager()));
}
private void loadItems() {
@@ -209,11 +217,8 @@ public abstract class NamedListFragment<T extends Named> extends LoggableListFra
manager.beginTransaction().add(dialog, "failedDialog").commitAllowingStateLoss();
}
private void showProgressBar(boolean visible) {
Activity activity = getActivity();
if (activity != null) {
activity.setProgressBarIndeterminateVisibility(visible);
}
void showProgressBar(boolean visible) {
footerView.setVisibility(visible ? View.VISIBLE : View.GONE);
}
protected void selectItem(T eventBase) {
@@ -236,7 +236,7 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment {
.createConfigurationLoader(deviceConfigurationName, deviceConfigurationUuid, new LoadClient<DeviceConfiguration>() {
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
if (reason instanceof FileNotFoundException) {
Toast.makeText(getActivity(),
getString(R.string.loading_configuration_not_found),
@@ -256,7 +256,7 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment {
}
@Override
public void onLoadSucceeded(DeviceConfiguration configuration,
public void onLoadSucceeded(int loaderId, DeviceConfiguration configuration,
boolean isCached) {
getLoaderManager().destroyLoader(0);
@@ -246,14 +246,14 @@ public class CourseFragmentMarks extends CourseFragment
Loader<?> marksLoader = getLoaderManager().restartLoader(0, null,
mDataManager.createMarksLoader(getRace(), new LoadClient<Collection<Mark>>() {
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
String toastText = getString(R.string.marks_w_placeholder);
Toast.makeText(getActivity(), String.format(toastText, reason.toString()), Toast.LENGTH_LONG)
.show();
}
@Override
public void onLoadSucceeded(Collection<Mark> data, boolean isCached) {
public void onLoadSucceeded(int loaderId, Collection<Mark> data, boolean isCached) {
onLoadMarksSucceeded(data);
}
}));
@@ -375,13 +375,13 @@ public class PenaltyFragment extends BaseFragment
final Loader<?> competitorLoader = getLoaderManager().initLoader(COMPETITOR_LOADER, null,
dataManager.createCompetitorsLoader(getRace(), new LoadClient<Map<Competitor, Boat>>() {
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
Toast.makeText(getActivity(), getString(R.string.competitor_load_error, reason.toString()),
Toast.LENGTH_LONG).show();
}
@Override
public void onLoadSucceeded(Map<Competitor, Boat> data, boolean isCached) {
public void onLoadSucceeded(int loaderId, Map<Competitor, Boat> data, boolean isCached) {
if (isAdded() && !isCached) {
onLoadCompetitorsSucceeded(data);
}
@@ -396,11 +396,11 @@ public class PenaltyFragment extends BaseFragment
final Loader<?> leaderboardResultLoader = getLoaderManager().initLoader(LEADERBOARD_ORDER_LOADER, null,
dataManager.createLeaderboardLoader(getRace(), new LoadClient<LeaderboardResult>() {
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
}
@Override
public void onLoadSucceeded(LeaderboardResult data, boolean isCached) {
public void onLoadSucceeded(int loaderId, LeaderboardResult data, boolean isCached) {
onLoadLeaderboardResultSucceeded(data);
}
}));
@@ -457,13 +457,13 @@ public class TrackingListFragment extends BaseFragment
dataManager.createCompetitorsLoader(getRace(), new LoadClient<Map<Competitor, Boat>>() {
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
Toast.makeText(getActivity(), getString(R.string.competitor_load_error, reason.toString()),
Toast.LENGTH_LONG).show();
}
@Override
public void onLoadSucceeded(Map<Competitor, Boat> data, boolean isCached) {
public void onLoadSucceeded(int loaderId, Map<Competitor, Boat> data, boolean isCached) {
if (isAdded() && !isCached) {
onLoadCompetitorsSucceeded(data);
}
@@ -480,11 +480,11 @@ public class TrackingListFragment extends BaseFragment
final Loader<?> leaderboardResultLoader = getLoaderManager().initLoader(LEADERBOARD_ORDER_LOADER, null,
dataManager.createLeaderboardLoader(getRace(), new LoadClient<LeaderboardResult>() {
@Override
public void onLoadFailed(Exception reason) {
public void onLoadFailed(int loaderId, Exception reason) {
}
@Override
public void onLoadSucceeded(LeaderboardResult data, boolean isCached) {
public void onLoadSucceeded(int loaderId, LeaderboardResult data, boolean isCached) {
List<Util.Pair<Long, String>> sortByRank = data.getResult(getRace().getName());
if (isAdded() && sortByRank != null) {
CompetitorGoalPassingComparator comparator = (CompetitorGoalPassingComparator) mComparators