diff options
author | Portree-Kid <keith.paterson@gmx.de> | 2013-03-08 15:06:41 +0100 |
---|---|---|
committer | Portree-Kid <keith.paterson@gmx.de> | 2013-03-08 15:06:41 +0100 |
commit | a0932683fdf840fd97464e93a4597fac5c93a731 (patch) | |
tree | a0e27bbad9012436d378da27f3e2b052a0edb2f3 /main/src | |
parent | cfb16fb725c069f59d545a50ba40045320a55c2c (diff) | |
download | cgeo-a0932683fdf840fd97464e93a4597fac5c93a731.zip cgeo-a0932683fdf840fd97464e93a4597fac5c93a731.tar.gz cgeo-a0932683fdf840fd97464e93a4597fac5c93a731.tar.bz2 |
Refactoring to use Loaders fixes #2365
Diffstat (limited to 'main/src')
17 files changed, 595 insertions, 463 deletions
diff --git a/main/src/cgeo/geocaching/cgData.java b/main/src/cgeo/geocaching/cgData.java index c17eb15..7e9b37a 100644 --- a/main/src/cgeo/geocaching/cgData.java +++ b/main/src/cgeo/geocaching/cgData.java @@ -2896,10 +2896,10 @@ public class cgData { return cgData.getBounds(Collections.singleton(geocode)); } - public static void clearVisitDate(List<Geocache> caches) { - ArrayList<String> geocodes = new ArrayList<String>(caches.size()); - for (Geocache cache : caches) { - geocodes.add(cache.getGeocode()); + public static void clearVisitDate(String[] selected) { + ArrayList<String> geocodes = new ArrayList<String>(); + for (int i = 0; i < selected.length; i++) { + geocodes.add(selected[i]); } setVisitDate(geocodes, 0); } diff --git a/main/src/cgeo/geocaching/cgeocaches.java b/main/src/cgeo/geocaching/cgeocaches.java index 171149d..726b60e 100644 --- a/main/src/cgeo/geocaching/cgeocaches.java +++ b/main/src/cgeo/geocaching/cgeocaches.java @@ -7,10 +7,6 @@ import cgeo.geocaching.activity.FilteredActivity; import cgeo.geocaching.activity.Progress; import cgeo.geocaching.apps.cache.navi.NavigationAppFactory; import cgeo.geocaching.apps.cachelist.CacheListAppFactory; -import cgeo.geocaching.connector.ConnectorFactory; -import cgeo.geocaching.connector.capability.ISearchByCenter; -import cgeo.geocaching.connector.gc.AbstractSearchThread; -import cgeo.geocaching.connector.gc.GCParser; import cgeo.geocaching.connector.gc.SearchHandler; import cgeo.geocaching.enumerations.CacheListType; import cgeo.geocaching.enumerations.CacheType; @@ -21,6 +17,16 @@ import cgeo.geocaching.files.GPXImporter; import cgeo.geocaching.filter.FilterUserInterface; import cgeo.geocaching.filter.IFilter; import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.loaders.AbstractSearchLoader; +import cgeo.geocaching.loaders.AbstractSearchLoader.CacheListLoaderType; +import cgeo.geocaching.loaders.AddressGeocacheListLoader; +import cgeo.geocaching.loaders.CoordsGeocacheListLoader; +import cgeo.geocaching.loaders.HistoryGeocacheListLoader; +import cgeo.geocaching.loaders.KeywordGeocacheListLoader; +import cgeo.geocaching.loaders.OfflineGeocacheListLoader; +import cgeo.geocaching.loaders.OwnerGeocacheListLoader; +import cgeo.geocaching.loaders.RemoveFromHistoryLoader; +import cgeo.geocaching.loaders.UsernameGeocacheListLoader; import cgeo.geocaching.maps.CGeoMap; import cgeo.geocaching.network.Cookies; import cgeo.geocaching.network.Network; @@ -47,10 +53,13 @@ import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.KeyEvent; @@ -70,8 +79,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -public class cgeocaches extends AbstractListActivity implements FilteredActivity { +public class cgeocaches extends AbstractListActivity implements FilteredActivity, LoaderManager.LoaderCallbacks<SearchResult> { + private static final String EXTRA_CACHELIST = "CACHELIST"; private static final int MAX_LIST_ITEMS = 1000; private static final int MENU_REFRESH_STORED = 2; private static final int MENU_CACHE_DETAILS = 4; @@ -120,12 +130,12 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity private long detailProgressTime = 0L; private LoadDetailsThread threadDetails = null; private LoadFromWebThread threadWeb = null; - private int listId = StoredList.TEMPORARY_LIST_ID; // Only meaningful for the OFFLINE type + private int listId = StoredList.TEMPORARY_LIST_ID; // Only meaningful for the OFFLINE type private final GeoDirHandler geoDirHandler = new GeoDirHandler() { @Override public void updateGeoData(final IGeoData geo) { - if (geo.getCoords() != null) { + if (geo.getCoords() != null) { adapter.setActualCoordinates(geo.getCoords()); } if (!Settings.isUseCompass() || geo.getSpeed() > 5) { // use GPS when speed is higher than 18 km/h @@ -145,7 +155,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } - }; + }; private ContextMenuInfo lastMenuInfo; private String contextMenuGeocode = ""; /** @@ -237,42 +247,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } - private Handler loadNextPageHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - try { - replaceCacheListFromSearch(); - setAdapter(); - - updateTitle(); - - showFooterMoreCaches(); - - if (search != null && search.getError() != null) { - showToast(res.getString(R.string.err_download_fail) + " " + search.getError().getErrorString(res) + "."); - - listFooter.setOnClickListener(new MoreCachesListener()); - hideLoading(); - showProgress(false); - - finish(); - return; - } - - setAdapterCurrentCoordinates(false); - } catch (Exception e) { - showToast(res.getString(R.string.err_detail_cache_find_next)); - Log.e("cgeocaches.loadNextPageHandler", e); - } - - hideLoading(); - showProgress(false); - - adapter.setSelectMode(false); - } - }; - /** * Loads the caches and fills the {@link #cacheList} according to {@link #search} content. * @@ -332,8 +306,8 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity progress.setProgress(detailProgress); if (minutesRemaining < 1) { progress.setMessage(res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm)); - } else { - progress.setMessage(res.getString(R.string.caches_downloading) + " " + minutesRemaining + " " + res.getQuantityString(R.plurals.caches_eta_mins,minutesRemaining)); + } else { + progress.setMessage(res.getString(R.string.caches_downloading) + " " + minutesRemaining + " " + res.getQuantityString(R.plurals.caches_eta_mins, minutesRemaining)); } } else if (msg.what == MSG_CANCEL) { if (threadDetails != null) { @@ -413,24 +387,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } }; - private Handler removeFromHistoryHandler = new Handler() { - - @Override - public void handleMessage(Message msg) { - setAdapter(); - - if (msg.what > -1) { - progress.setProgress(detailProgress); - } else { - adapter.setSelectMode(false); - - // reload history list - (new LoadByHistoryThread()).start(); - - progress.dismiss(); - } - } - }; private Handler importGpxAttachementFinishedHandler = new Handler() { @Override @@ -438,6 +394,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity refreshCurrentList(); } }; + private AbstractSearchLoader currentLoader; public cgeocaches() { super(true); @@ -467,133 +424,23 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } + currentLoader = (AbstractSearchLoader) getSupportLoaderManager().initLoader(type.ordinal(), extras, this); + // init if (CollectionUtils.isNotEmpty(cacheList)) { - showFooterMoreCaches(); + if (currentLoader.isStarted()) + { + showFooterLoadingCaches(); + } + else + { + showFooterMoreCaches(); + } } setTitle(title); setAdapter(); - Thread threadPure; - AbstractSearchThread thread; - - final String username = extras.getString(Intents.EXTRA_USERNAME); - switch (type) { - case OFFLINE: - listId = Settings.getLastList(); - if (listId <= StoredList.TEMPORARY_LIST_ID) { - listId = StoredList.STANDARD_LIST_ID; - title = res.getString(R.string.stored_caches_button); - } else { - final StoredList list = cgData.getList(listId); - // list.id may be different if listId was not valid - listId = list.id; - title = list.title; - } - - setTitle(title); - showProgress(true); - showFooterLoadingCaches(); - - threadPure = new LoadByOfflineThread(coords, listId); - threadPure.start(); - - break; - case HISTORY: - title = res.getString(R.string.caches_history); - setTitle(title); - showProgress(true); - showFooterLoadingCaches(); - - threadPure = new LoadByHistoryThread(); - threadPure.start(); - break; - case NEAREST: - title = res.getString(R.string.caches_nearby); - setTitle(title); - showProgress(true); - showFooterLoadingCaches(); - - thread = new LoadByCoordsThread(coords); - thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); - thread.start(); - break; - case COORDINATE: - title = coords.toString(); - setTitle(title); - showProgress(true); - showFooterLoadingCaches(); - - thread = new LoadByCoordsThread(coords); - thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); - thread.start(); - break; - case KEYWORD: - final String keyword = extras.getString(Intents.EXTRA_KEYWORD); - title = keyword; - setTitle(title); - showProgress(true); - showFooterLoadingCaches(); - - thread = new LoadByKeywordThread(keyword); - thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); - thread.start(); - break; - case ADDRESS: - final String address = extras.getString(Intents.EXTRA_ADDRESS); - if (StringUtils.isNotBlank(address)) { - title = address; - } else { - title = coords.toString(); - } - setTitle(title); - showProgress(true); - showFooterLoadingCaches(); - - if (coords != null) { - thread = new LoadByCoordsThread(coords); - } - else { - thread = new LoadByAddressThread(address); - } - thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); - thread.start(); - break; - case USERNAME: - title = username; - setTitle(title); - showProgress(true); - showFooterLoadingCaches(); - - thread = new LoadByUserNameThread(username); - thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); - thread.start(); - break; - case OWNER: - title = username; - setTitle(title); - showProgress(true); - showFooterLoadingCaches(); - - thread = new LoadByOwnerThread(username); - thread.setRecaptchaHandler(new SearchHandler(this, res, thread)); - thread.start(); - break; - case MAP: - title = res.getString(R.string.map_map); - setTitle(title); - showProgress(true); - search = (SearchResult) extras.get(Intents.EXTRA_SEARCH); - replaceCacheListFromSearch(); - loadCachesHandler.sendMessage(Message.obtain()); - break; - default: - title = "caches"; - setTitle(title); - Log.e("cgeocaches.onCreate: No action or unknown action specified"); - break; - } prepareFilterBar(); if (isInvokedFromAttachment()) { @@ -601,6 +448,15 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + if (currentLoader.isLoading()) + { + showFooterLoadingCaches(); + } + } + private boolean isConcreteList() { return type == CacheListType.OFFLINE && (listId == StoredList.STANDARD_LIST_ID || listId >= cgData.customListIdOffset); @@ -1158,14 +1014,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } private void startGeoAndDir() { - geoDirHandler.startGeo(); - if (Settings.isLiveMap()) { - geoDirHandler.startDir(); - } + geoDirHandler.startGeo(); + if (Settings.isLiveMap()) { + geoDirHandler.startDir(); + } } private void removeGeoAndDir() { - geoDirHandler.stopGeoAndDir(); + geoDirHandler.stopGeoAndDir(); } private void importGpx() { @@ -1208,7 +1064,7 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity if (etaTime < 1) { message = res.getString(R.string.caches_downloading) + " " + res.getString(R.string.caches_eta_ltm); } else { - message = res.getString(R.string.caches_downloading) + " " + etaTime + " " + res.getQuantityString(R.plurals.caches_eta_mins,etaTime); + message = res.getString(R.string.caches_downloading) + " " + etaTime + " " + res.getQuantityString(R.plurals.caches_eta_mins, etaTime); } progress.show(this, null, message, ProgressDialog.STYLE_HORIZONTAL, loadDetailsHandler.obtainMessage(MSG_CANCEL)); @@ -1245,14 +1101,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } public void removeFromHistory() { - detailTotal = adapter.getCheckedOrAllCount(); - detailProgress = 0; - - showProgress(false); - progress.show(this, null, res.getString(R.string.caches_removing_from_history), ProgressDialog.STYLE_HORIZONTAL, removeFromHistoryHandler.obtainMessage(MSG_CANCEL)); - progress.setMaxProgressAndReset(detailTotal); + ArrayList<String> geocodes = new ArrayList<String>(adapter.getCheckedOrAllCaches().size()); + for (Geocache cache : adapter.getCheckedOrAllCaches()) { + geocodes.add(cache.getGeocode()); + } - new RemoveFromHistoryThread(removeFromHistoryHandler).start(); + Bundle b = new Bundle(); + b.putStringArray(EXTRA_CACHELIST, geocodes.toArray(new String[geocodes.size()])); + getSupportLoaderManager().initLoader(CacheListLoaderType.REMOVE_FROM_HISTORY.ordinal(), b, this); } public void importWeb() { @@ -1303,128 +1159,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity new DropDetailsThread(dropDetailsHandler, adapter.getCheckedOrAllCaches()).start(); } - private class LoadByOfflineThread extends Thread { - final private Geopoint coords; - final private int listId; - - public LoadByOfflineThread(final Geopoint coordsIn, int listIdIn) { - coords = coordsIn; - listId = listIdIn; - } - - @Override - public void run() { - search = cgData.getBatchOfStoredCaches(coords, Settings.getCacheType(), listId); - replaceCacheListFromSearch(); - loadCachesHandler.sendMessage(Message.obtain()); - } - } - - private class LoadByHistoryThread extends Thread { - @Override - public void run() { - search = cgData.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL); - replaceCacheListFromSearch(); - loadCachesHandler.sendMessage(Message.obtain()); - } - } - - private class LoadNextPageThread extends AbstractSearchThread { - public LoadNextPageThread() { - super(loadNextPageHandler); - } - - @Override - public void runSearch() { - search = GCParser.searchByNextPage(search, Settings.isShowCaptcha()); - } - } - - private class LoadByCoordsThread extends AbstractSearchThread { - final private Geopoint coords; - - public LoadByCoordsThread(final Geopoint coords) { - super(loadCachesHandler); - this.coords = coords; - } - - @Override - public void runSearch() { - - search = GCParser.searchByCoords(coords, Settings.getCacheType(), Settings.isShowCaptcha()); - - for (ISearchByCenter centerConn : ConnectorFactory.getSearchByCenterConnectors()) { - if (centerConn.isActivated()) { - SearchResult temp = centerConn.searchByCenter(coords); - if (temp != null) { - search.addGeocodes(temp.getGeocodes()); - } - } - } - replaceCacheListFromSearch(); - } - } - - private class LoadByKeywordThread extends AbstractSearchThread { - final private String keyword; - - public LoadByKeywordThread(final String keyword) { - super(loadCachesHandler); - this.keyword = keyword; - } - - @Override - public void runSearch() { - search = GCParser.searchByKeyword(keyword, Settings.getCacheType(), Settings.isShowCaptcha()); - replaceCacheListFromSearch(); - } - } - - private class LoadByUserNameThread extends AbstractSearchThread { - final private String username; - - public LoadByUserNameThread(final String username) { - super(loadCachesHandler); - this.username = username; - } - - @Override - public void runSearch() { - search = GCParser.searchByUsername(username, Settings.getCacheType(), Settings.isShowCaptcha()); - replaceCacheListFromSearch(); - } - } - - private class LoadByOwnerThread extends AbstractSearchThread { - final private String username; - - public LoadByOwnerThread(final String username) { - super(loadCachesHandler); - this.username = username; - } - - @Override - public void runSearch() { - search = GCParser.searchByOwner(username, Settings.getCacheType(), Settings.isShowCaptcha()); - replaceCacheListFromSearch(); - } - } - - private class LoadByAddressThread extends AbstractSearchThread { - final private String address; - - public LoadByAddressThread(final String address) { - super(loadCachesHandler); - this.address = address; - } - - @Override - public void runSearch() { - search = GCParser.searchByAddress(address, Settings.getCacheType(), Settings.isShowCaptcha()); - replaceCacheListFromSearch(); - } - } - /** * Thread to refresh the cache details. */ @@ -1627,23 +1361,6 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity } } - private class RemoveFromHistoryThread extends Thread { - - final private Handler handler; - final private List<Geocache> selected; - - public RemoveFromHistoryThread(Handler handlerIn) { - handler = handlerIn; - selected = adapter.getCheckedOrAllCaches(); - } - - @Override - public void run() { - cgData.clearVisitDate(selected); - handler.sendEmptyMessage(MSG_DONE); - } - } - private class MoreCachesListener implements View.OnClickListener { @Override @@ -1652,9 +1369,8 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity showFooterLoadingCaches(); listFooter.setOnClickListener(null); - final LoadNextPageThread thread = new LoadNextPageThread(); - thread.setRecaptchaHandler(new SearchHandler(cgeocaches.this, res, thread)); - thread.start(); + currentLoader.startLoading(); + // currentLoader.forceLoad(); } } @@ -1701,40 +1417,14 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity showProgress(true); showFooterLoadingCaches(); + final List<Geocache> caches = adapter.getCheckedCaches(); + cgData.moveToList(caches, listId); - (new MoveCachesToListThread(listId, new MoveHandler())).start(); - invalidateOptionsMenuCompatible(); - } - - /** - * TODO Possible refactoring. IMO The Handler is obsolete - * @author keith.paterson - * - */ + currentLoader = (AbstractSearchLoader) getSupportLoaderManager().initLoader(CacheListType.OFFLINE.ordinal(), new Bundle(), this); + currentLoader.reset(); + currentLoader.startLoading(); - private class MoveHandler extends Handler { - @Override - public void handleMessage(Message msg) { - Thread threadPure = new LoadByOfflineThread(coords, msg.what); - threadPure.start(); - } - } - - private class MoveCachesToListThread extends Thread { - final private int listId; - final private Handler handler; - - public MoveCachesToListThread(int listIdIn, Handler handlerIn) { - listId = listIdIn; - handler = handlerIn; - } - - @Override - public void run() { - final List<Geocache> caches = adapter.getCheckedCaches(); - cgData.moveToList(caches, listId); - handler.sendEmptyMessage(listId); - } + invalidateOptionsMenuCompatible(); } private void renameList() { @@ -1970,4 +1660,153 @@ public class cgeocaches extends AbstractListActivity implements FilteredActivity cachesIntent.putExtra(Intents.EXTRA_SEARCH, search); context.startActivity(cachesIntent); } + + // Loaders + + @Override + public Loader<SearchResult> onCreateLoader(int type, Bundle extras) { + AbstractSearchLoader loader = null; + CacheListLoaderType enumType = CacheListLoaderType.values()[type]; + final String username = extras.getString(Intents.EXTRA_USERNAME); + switch (enumType) { + case OFFLINE: + listId = Settings.getLastList(); + if (listId <= StoredList.TEMPORARY_LIST_ID) { + listId = StoredList.STANDARD_LIST_ID; + title = res.getString(R.string.stored_caches_button); + } else { + final StoredList list = cgData.getList(listId); + // list.id may be different if listId was not valid + listId = list.id; + title = list.title; + } + + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + loader = new OfflineGeocacheListLoader(this.getBaseContext(), coords, listId); + + break; + case HISTORY: + title = res.getString(R.string.caches_history); + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + loader = new HistoryGeocacheListLoader(app, coords); + break; + case NEAREST: + title = res.getString(R.string.caches_nearby); + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + loader = new CoordsGeocacheListLoader(app, coords); + break; + case COORDINATE: + title = coords.toString(); + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + loader = new CoordsGeocacheListLoader(app, coords); + break; + case KEYWORD: + final String keyword = extras.getString(Intents.EXTRA_KEYWORD); + title = keyword; + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + loader = new KeywordGeocacheListLoader(app, keyword); + break; + case ADDRESS: + final String address = extras.getString(Intents.EXTRA_ADDRESS); + if (StringUtils.isNotBlank(address)) { + title = address; + } else { + title = coords.toString(); + } + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + if (coords != null) { + loader = new CoordsGeocacheListLoader(app, coords); + } + else { + loader = new AddressGeocacheListLoader(app, address); + } + break; + case USERNAME: + title = username; + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + loader = new UsernameGeocacheListLoader(app, username); + break; + case OWNER: + title = username; + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + loader = new OwnerGeocacheListLoader(app, username); + break; + case MAP: + //TODO Build Nullloader + title = res.getString(R.string.map_map); + setTitle(title); + showProgress(true); + search = (SearchResult) extras.get(Intents.EXTRA_SEARCH); + replaceCacheListFromSearch(); + loadCachesHandler.sendMessage(Message.obtain()); + break; + case REMOVE_FROM_HISTORY: + title = res.getString(R.string.caches_history); + setTitle(title); + showProgress(true); + showFooterLoadingCaches(); + + loader = new RemoveFromHistoryLoader(app, extras.getStringArray(EXTRA_CACHELIST), coords); + break; + + default: + title = "caches"; + setTitle(title); + Log.e("cgeocaches.onCreate: No action or unknown action specified"); + break; + } + if (loader != null) { + loader.setRecaptchaHandler(new SearchHandler(this, res, loader)); + } + return loader; + } + + @Override + public void onLoadFinished(Loader<SearchResult> arg0, SearchResult searchIn) { + // The database search was moved into the UI call intentionally. If this is done before the runOnUIThread, + // then we have 2 sets of caches in memory. This can lead to OOM for huge cache lists. + if (searchIn != null) + { + cacheList.clear(); + final Set<Geocache> cachesFromSearchResult = searchIn.getCachesFromSearchResult(LoadFlags.LOAD_CACHE_OR_DB); + cacheList.addAll(cachesFromSearchResult); + search = searchIn; + adapter.reFilter(); + updateTitle(); + showFooterMoreCaches(); + } + showProgress(false); + hideLoading(); + } + + @Override + public void onLoaderReset(Loader<SearchResult> arg0) { + // TODO Auto-generated method stub + + } } + diff --git a/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java b/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java deleted file mode 100644 index f19064d..0000000 --- a/main/src/cgeo/geocaching/connector/gc/AbstractSearchThread.java +++ /dev/null @@ -1,68 +0,0 @@ -package cgeo.geocaching.connector.gc; - -import cgeo.geocaching.utils.Log; - -import android.os.Handler; -import android.os.Message; - -abstract public class AbstractSearchThread extends Thread { - private Handler recaptchaHandler = null; - private String recaptchaChallenge = null; - private String recaptchaText = null; - private final Handler handler; - private static AbstractSearchThread currentInstance; - - protected AbstractSearchThread(final Handler handler) { - this.handler = handler; - } - - public void setRecaptchaHandler(Handler recaptchaHandlerIn) { - recaptchaHandler = recaptchaHandlerIn; - } - - public void notifyNeed() { - if (recaptchaHandler != null) { - recaptchaHandler.sendEmptyMessage(1); - } - } - - public synchronized void waitForUser() { - try { - wait(); - } catch (InterruptedException e) { - Log.w("searchThread is not waiting for user…"); - } - } - - public void setChallenge(String challenge) { - recaptchaChallenge = challenge; - } - - public String getChallenge() { - return recaptchaChallenge; - } - - public synchronized void setText(String text) { - recaptchaText = text; - - notify(); - } - - public synchronized String getText() { - return recaptchaText; - } - - @Override - final public void run() { - super.run(); - currentInstance = this; - runSearch(); - handler.sendMessage(Message.obtain()); - } - - protected abstract void runSearch(); - - public static AbstractSearchThread getCurrentInstance() { - return currentInstance; - } -} diff --git a/main/src/cgeo/geocaching/connector/gc/GCMap.java b/main/src/cgeo/geocaching/connector/gc/GCMap.java index 2e1dff0..5f16e10 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCMap.java +++ b/main/src/cgeo/geocaching/connector/gc/GCMap.java @@ -1,8 +1,8 @@ package cgeo.geocaching.connector.gc; +import cgeo.geocaching.Geocache; import cgeo.geocaching.SearchResult; import cgeo.geocaching.Settings; -import cgeo.geocaching.Geocache; import cgeo.geocaching.cgData; import cgeo.geocaching.cgeoapplication; import cgeo.geocaching.enumerations.CacheSize; @@ -352,7 +352,8 @@ public class GCMap { if (strategy.flags.contains(StrategyFlag.SEARCH_NEARBY)) { final Geopoint center = viewport.getCenter(); if ((lastSearchViewport == null) || !lastSearchViewport.contains(center)) { - SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false); + //FIXME We don't have a RecaptchaReceiver!? + SearchResult search = GCParser.searchByCoords(center, Settings.getCacheType(), false, null); if (search != null && !search.isEmpty()) { final Set<String> geocodes = search.getGeocodes(); if (Settings.isPremiumMember()) { diff --git a/main/src/cgeo/geocaching/connector/gc/GCParser.java b/main/src/cgeo/geocaching/connector/gc/GCParser.java index 9707e06..9561b87 100644 --- a/main/src/cgeo/geocaching/connector/gc/GCParser.java +++ b/main/src/cgeo/geocaching/connector/gc/GCParser.java @@ -24,6 +24,7 @@ import cgeo.geocaching.gcvote.GCVote; import cgeo.geocaching.gcvote.GCVoteRating; import cgeo.geocaching.geopoint.DistanceParser; import cgeo.geocaching.geopoint.Geopoint; +import cgeo.geocaching.loaders.RecaptchaReceiver; import cgeo.geocaching.network.Network; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.ui.DirectionImage; @@ -62,7 +63,7 @@ public abstract class GCParser { private final static SimpleDateFormat dateTbIn1 = new SimpleDateFormat("EEEEE, dd MMMMM yyyy", Locale.ENGLISH); // Saturday, 28 March 2009 private final static SimpleDateFormat dateTbIn2 = new SimpleDateFormat("EEEEE, MMMMM dd, yyyy", Locale.ENGLISH); // Saturday, March 28, 2009 - private static SearchResult parseSearch(final String url, final String pageContent, final boolean showCaptcha) { + private static SearchResult parseSearch(final String url, final String pageContent, final boolean showCaptcha, RecaptchaReceiver thread) { if (StringUtils.isBlank(pageContent)) { Log.e("GCParser.parseSearch: No page given"); return null; @@ -76,7 +77,6 @@ public abstract class GCParser { searchResult.viewstates = Login.getViewstates(page); // recaptcha - AbstractSearchThread thread = AbstractSearchThread.getCurrentInstance(); String recaptchaChallenge = null; if (showCaptcha) { String recaptchaJsParam = BaseUtils.getMatch(page, GCConstants.PATTERN_SEARCH_RECAPTCHA, false, null); @@ -702,7 +702,7 @@ public abstract class GCParser { return searchResult; } - public static SearchResult searchByNextPage(final SearchResult search, boolean showCaptcha) { + public static SearchResult searchByNextPage(final SearchResult search, boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { if (search == null) { return search; } @@ -739,7 +739,7 @@ public abstract class GCParser { return search; } - final SearchResult searchResult = parseSearch(url, page, showCaptcha); + final SearchResult searchResult = parseSearch(url, page, showCaptcha, recaptchaReceiver); if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) { Log.w("GCParser.searchByNextPage: No cache parsed"); return search; @@ -784,9 +784,10 @@ public abstract class GCParser { * @param showCaptcha * @param params * the parameters to add to the request URI + * @param recaptchaReceiver * @return */ - private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params) { + private static SearchResult searchByAny(final CacheType cacheType, final boolean my, final boolean showCaptcha, final Parameters params, RecaptchaReceiver recaptchaReceiver) { insertCacheType(params, cacheType); final String uri = "http://www.geocaching.com/seek/nearest.aspx"; @@ -798,7 +799,7 @@ public abstract class GCParser { return null; } - final SearchResult searchResult = parseSearch(fullUri, page, showCaptcha); + final SearchResult searchResult = parseSearch(fullUri, page, showCaptcha, recaptchaReceiver); if (searchResult == null || CollectionUtils.isEmpty(searchResult.getGeocodes())) { Log.e("GCParser.searchByAny: No cache parsed"); return searchResult; @@ -811,22 +812,22 @@ public abstract class GCParser { return search; } - public static SearchResult searchByCoords(final Geopoint coords, final CacheType cacheType, final boolean showCaptcha) { + public static SearchResult searchByCoords(final Geopoint coords, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { final Parameters params = new Parameters("lat", Double.toString(coords.getLatitude()), "lng", Double.toString(coords.getLongitude())); - return searchByAny(cacheType, false, showCaptcha, params); + return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByKeyword(final String keyword, final CacheType cacheType, final boolean showCaptcha) { + public static SearchResult searchByKeyword(final String keyword, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(keyword)) { Log.e("GCParser.searchByKeyword: No keyword given"); return null; } final Parameters params = new Parameters("key", keyword); - return searchByAny(cacheType, false, showCaptcha, params); + return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha) { + public static SearchResult searchByUsername(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(userName)) { Log.e("GCParser.searchByUsername: No user name given"); return null; @@ -840,20 +841,20 @@ public abstract class GCParser { Log.i("GCParser.searchByUsername: Overriding users choice, downloading all caches."); } - return searchByAny(cacheType, my, showCaptcha, params); + return searchByAny(cacheType, my, showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha) { + public static SearchResult searchByOwner(final String userName, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(userName)) { Log.e("GCParser.searchByOwner: No user name given"); return null; } final Parameters params = new Parameters("u", userName); - return searchByAny(cacheType, false, showCaptcha, params); + return searchByAny(cacheType, false, showCaptcha, params, recaptchaReceiver); } - public static SearchResult searchByAddress(final String address, final CacheType cacheType, final boolean showCaptcha) { + public static SearchResult searchByAddress(final String address, final CacheType cacheType, final boolean showCaptcha, RecaptchaReceiver recaptchaReceiver) { if (StringUtils.isBlank(address)) { Log.e("GCParser.searchByAddress: No address given"); return null; @@ -873,7 +874,7 @@ public abstract class GCParser { if (data == null) { return null; } - return searchByCoords(new Geopoint(data.getDouble("lat"), data.getDouble("lng")), cacheType, showCaptcha); + return searchByCoords(new Geopoint(data.getDouble("lat"), data.getDouble("lng")), cacheType, showCaptcha, recaptchaReceiver); } catch (JSONException e) { Log.w("GCParser.searchByAddress", e); } diff --git a/main/src/cgeo/geocaching/connector/gc/SearchHandler.java b/main/src/cgeo/geocaching/connector/gc/SearchHandler.java index 2351554..840cad1 100644 --- a/main/src/cgeo/geocaching/connector/gc/SearchHandler.java +++ b/main/src/cgeo/geocaching/connector/gc/SearchHandler.java @@ -1,6 +1,7 @@ package cgeo.geocaching.connector.gc; import cgeo.geocaching.R; +import cgeo.geocaching.loaders.RecaptchaReceiver; import cgeo.geocaching.utils.Log; import android.app.Activity; @@ -24,7 +25,7 @@ import java.net.URL; public class SearchHandler extends Handler { private Activity activity = null; private Resources res = null; - private AbstractSearchThread recaptchaThread = null; + private RecaptchaReceiver recaptchaThread = null; private ImageView imageView = null; private Bitmap img = null; @@ -41,7 +42,7 @@ public class SearchHandler extends Handler { } }; - public SearchHandler(Activity activityIn, Resources resIn, AbstractSearchThread recaptchaThreadIn) { + public SearchHandler(Activity activityIn, Resources resIn, RecaptchaReceiver recaptchaThreadIn) { activity = activityIn; res = resIn; recaptchaThread = recaptchaThreadIn; diff --git a/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java b/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java new file mode 100644 index 0000000..e178acc --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/AbstractSearchLoader.java @@ -0,0 +1,111 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.utils.Log; + +import android.content.Context; +import android.os.Handler; +import android.support.v4.content.AsyncTaskLoader; + +public abstract class AbstractSearchLoader extends AsyncTaskLoader<SearchResult> implements RecaptchaReceiver { + + public enum CacheListLoaderType { + OFFLINE, + HISTORY, + NEAREST, + COORDINATE, + KEYWORD, + ADDRESS, + USERNAME, + OWNER, + MAP, + REMOVE_FROM_HISTORY; + } + + private Handler recaptchaHandler = null; + private String recaptchaChallenge = null; + private String recaptchaText = null; + private SearchResult search; + private boolean loading; + + public boolean isLoading() { + return loading; + } + + public AbstractSearchLoader(Context context) { + super(context); + } + + public abstract SearchResult runSearch(); + + @Override + public SearchResult loadInBackground() { + loading = true; + if (search == null) { + search = runSearch(); + } else { + //Unless we make a new Search the Loader framework won't deliver results. It does't do equals only identity + SearchResult newSearch = new SearchResult(search); + newSearch.setUrl(search.getUrl()); + newSearch.setViewstates(search.getViewstates()); + search = GCParser.searchByNextPage(newSearch, Settings.isShowCaptcha(), this); + } + loading = false; + return search; + } + + @Override + public boolean takeContentChanged() { + return super.takeContentChanged(); + } + + @Override + protected void onStartLoading() { + forceLoad(); + } + + public void setRecaptchaHandler(Handler recaptchaHandlerIn) { + recaptchaHandler = recaptchaHandlerIn; + } + + @Override + public void notifyNeed() { + if (recaptchaHandler != null) { + recaptchaHandler.sendEmptyMessage(1); + } + } + + public synchronized void waitForUser() { + try { + wait(); + } catch (InterruptedException e) { + Log.w("searchThread is not waiting for user…"); + } + } + + @Override + public void setChallenge(String challenge) { + recaptchaChallenge = challenge; + } + + @Override + public String getChallenge() { + return recaptchaChallenge; + } + + @Override + public synchronized void setText(String text) { + recaptchaText = text; + + notify(); + } + + @Override + public synchronized String getText() { + return recaptchaText; + } + + +} diff --git a/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java new file mode 100644 index 0000000..6e4f99a --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/AddressGeocacheListLoader.java @@ -0,0 +1,23 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.connector.gc.GCParser; + +import android.content.Context; + +public class AddressGeocacheListLoader extends AbstractSearchLoader { + + private String address; + + public AddressGeocacheListLoader(Context context, String address) { + super(context); + this.address = address; + } + + @Override + public SearchResult runSearch() { + return GCParser.searchByAddress(address, Settings.getCacheType(), Settings.isShowCaptcha(), this); + } + +} diff --git a/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java new file mode 100644 index 0000000..2f76d49 --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/CoordsGeocacheListLoader.java @@ -0,0 +1,36 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.connector.ConnectorFactory; +import cgeo.geocaching.connector.capability.ISearchByCenter; +import cgeo.geocaching.connector.gc.GCParser; +import cgeo.geocaching.geopoint.Geopoint; + +import android.content.Context; + +public class CoordsGeocacheListLoader extends AbstractSearchLoader { + private Geopoint coords; + + public CoordsGeocacheListLoader(Context context, Geopoint coords) { + super(context); + this.coords = coords; + } + + @Override + public SearchResult runSearch() { + SearchResult search = GCParser.searchByCoords(coords, Settings.getCacheType(), Settings.isShowCaptcha(), this); + + for (ISearchByCenter centerConn : ConnectorFactory.getSearchByCenterConnectors()) { + if (centerConn.isActivated()) { + SearchResult temp = centerConn.searchByCenter(coords); + if (temp != null) { + search.addGeocodes(temp.getGeocodes()); + } + } + } + + return search; + } + +} diff --git a/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java new file mode 100644 index 0000000..59a5726 --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/HistoryGeocacheListLoader.java @@ -0,0 +1,26 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgData; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.geopoint.Geopoint; + +import android.content.Context; + +public class HistoryGeocacheListLoader extends AbstractSearchLoader { + + + private Geopoint coords; + + public HistoryGeocacheListLoader(Context context, Geopoint coords) { + super(context); + this.coords = coords; + } + + @Override + public SearchResult runSearch() { + return cgData.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL); + } + +} diff --git a/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java new file mode 100644 index 0000000..5f05e24 --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/KeywordGeocacheListLoader.java @@ -0,0 +1,23 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.connector.gc.GCParser; + +import android.content.Context; + +public class KeywordGeocacheListLoader extends AbstractSearchLoader { + + private String keyword; + + public KeywordGeocacheListLoader(Context context, String keyword) { + super(context); + this.keyword = keyword; + } + + @Override + public SearchResult runSearch() { + return GCParser.searchByKeyword(keyword, Settings.getCacheType(), Settings.isShowCaptcha(), this); + } + +} diff --git a/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java new file mode 100644 index 0000000..b05cc25 --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/NextPageGeocacheListLoader.java @@ -0,0 +1,22 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.connector.gc.GCParser; + +import android.content.Context; + +public class NextPageGeocacheListLoader extends AbstractSearchLoader { + private SearchResult search; + + public NextPageGeocacheListLoader(Context context, SearchResult search) { + super(context); + this.search = search; + } + + @Override + public SearchResult runSearch() { + return GCParser.searchByNextPage(search, Settings.isShowCaptcha(), this); + } + +} diff --git a/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java new file mode 100644 index 0000000..48e0ae3 --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/OfflineGeocacheListLoader.java @@ -0,0 +1,26 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgData; +import cgeo.geocaching.geopoint.Geopoint; + +import android.content.Context; + +public class OfflineGeocacheListLoader extends AbstractSearchLoader { + + private int listId; + private Geopoint searchCenter; + + public OfflineGeocacheListLoader(Context context, Geopoint searchCenter, int listId) { + super(context); + this.searchCenter = searchCenter; + this.listId = listId; + } + + @Override + public SearchResult runSearch() { + return cgData.getBatchOfStoredCaches(searchCenter, Settings.getCacheType(), listId); + } + +} diff --git a/main/src/cgeo/geocaching/loaders/OwnerGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/OwnerGeocacheListLoader.java new file mode 100644 index 0000000..a7e44fd --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/OwnerGeocacheListLoader.java @@ -0,0 +1,23 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.connector.gc.GCParser; + +import android.content.Context; + +public class OwnerGeocacheListLoader extends AbstractSearchLoader { + + private String username; + + public OwnerGeocacheListLoader(Context context, String username) { + super(context); + this.username = username; + } + + @Override + public SearchResult runSearch() { + return GCParser.searchByOwner(username, Settings.getCacheType(), Settings.isShowCaptcha(), this); + } + +} diff --git a/main/src/cgeo/geocaching/loaders/RecaptchaReceiver.java b/main/src/cgeo/geocaching/loaders/RecaptchaReceiver.java new file mode 100644 index 0000000..f64bf89 --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/RecaptchaReceiver.java @@ -0,0 +1,17 @@ +package cgeo.geocaching.loaders; + +public interface RecaptchaReceiver { + + public String getText(); + + public void setText(String text); + + public String getChallenge(); + + public void setChallenge(String challenge); + + public void notifyNeed(); + + public void waitForUser(); + +} diff --git a/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java b/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java new file mode 100644 index 0000000..7e9ea8f --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/RemoveFromHistoryLoader.java @@ -0,0 +1,28 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.cgData; +import cgeo.geocaching.enumerations.CacheType; +import cgeo.geocaching.geopoint.Geopoint; + +import android.content.Context; + +public class RemoveFromHistoryLoader extends AbstractSearchLoader { + + private String[] selected; + private Geopoint coords; + + public RemoveFromHistoryLoader(Context context, String[] selected, Geopoint coords) { + super(context); + this.selected = selected; + this.coords = coords; + } + + @Override + public SearchResult runSearch() { + cgData.clearVisitDate(selected); + return cgData.getHistoryOfCaches(true, coords != null ? Settings.getCacheType() : CacheType.ALL); + } + +} diff --git a/main/src/cgeo/geocaching/loaders/UsernameGeocacheListLoader.java b/main/src/cgeo/geocaching/loaders/UsernameGeocacheListLoader.java new file mode 100644 index 0000000..e613d5a --- /dev/null +++ b/main/src/cgeo/geocaching/loaders/UsernameGeocacheListLoader.java @@ -0,0 +1,23 @@ +package cgeo.geocaching.loaders; + +import cgeo.geocaching.SearchResult; +import cgeo.geocaching.Settings; +import cgeo.geocaching.connector.gc.GCParser; + +import android.content.Context; + +public class UsernameGeocacheListLoader extends AbstractSearchLoader { + + private String username; + + public UsernameGeocacheListLoader(Context context, String username) { + super(context); + this.username = username; + } + + @Override + public SearchResult runSearch() { + return GCParser.searchByUsername(username, Settings.getCacheType(), Settings.isShowCaptcha(), this); + } + +} |