package cgeo.geocaching.loaders; import cgeo.geocaching.CacheListActivity; import cgeo.geocaching.R; import cgeo.geocaching.SearchResult; import cgeo.geocaching.connector.IConnector; import cgeo.geocaching.utils.Log; import android.app.Activity; import android.support.v4.content.AsyncTaskLoader; import android.widget.Toast; import java.lang.ref.WeakReference; import java.util.Collection; import io.reactivex.functions.Function; public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> { public enum CacheListLoaderType { OFFLINE, POCKET, HISTORY, NEAREST, COORDINATE, KEYWORD, ADDRESS, FINDER, OWNER, MAP, NEXT_PAGE; public int getLoaderId() { return ordinal(); } } private final WeakReference<Activity> activityRef; private SearchResult search; private boolean loading; private CacheListActivity.AfterLoadAction afterLoadAction = CacheListActivity.AfterLoadAction.NO_ACTION; private static class NoConnectorException extends RuntimeException { /** * */ private static final long serialVersionUID = -3068184330294931088L; } /** * Run {@link SearchResult#parallelCombineActive(Collection, Function)} if there is at least one active connector * in <tt>connectors</tt>, and throw <tt>NoConnectorException</tt> otherwise. * * @param connectors * a collection of connectors * @param func * a function to apply to every connector * @param <C> * the type of connectors * @return the result of {@link SearchResult#parallelCombineActive(Collection, Function)} if there is at least one * active connector */ protected static <C extends IConnector> SearchResult nonEmptyCombineActive(final Collection<C> connectors, final Function<C, SearchResult> func) { for (final IConnector connector : connectors) { if (connector.isActive()) { return SearchResult.parallelCombineActive(connectors, func); } } throw new NoConnectorException(); } protected AbstractSearchLoader(final Activity activity) { super(activity); this.activityRef = new WeakReference<>(activity); } public abstract SearchResult runSearch(); public boolean isLoading() { return loading; } @Override public SearchResult loadInBackground() { loading = true; try { if (search == null) { search = runSearch(); } else { // Unless we make a new Search the Loader framework won't deliver results. It doesn't do equals only identity search = new SearchResult(search); } } catch (final NoConnectorException ignored) { final Activity activity = activityRef.get(); if (activity != null) { activity.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(activity, R.string.warn_no_connector, Toast.LENGTH_LONG).show(); activity.finish(); } }); } } catch (final Exception e) { Log.e("Error in Loader ", e); } loading = false; if (search == null) { search = new SearchResult(); } return search; } @Override protected void onStartLoading() { forceLoad(); } @Override public void reset() { super.reset(); search = null; } public CacheListActivity.AfterLoadAction getAfterLoadAction() { return afterLoadAction; } public void setAfterLoadAction(final CacheListActivity.AfterLoadAction afterLoadAction) { this.afterLoadAction = afterLoadAction; } }