<NME> CachePopup.java
<BEF> package cgeo.geocaching;

import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
import cgeo.geocaching.geopoint.Geopoint;
import cgeo.geocaching.ui.CacheDetailsCreator;
import android.app.Activity;
import android.content.Context;

import org.apache.commons.lang3.StringUtils;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;

import org.apache.commons.lang3.StringUtils;

import android.widget.TextView;

public class CachePopup extends AbstractPopupActivity {
    private ProgressDialog storeDialog = null;
    private ProgressDialog dropDialog = null;
    private final CancellableHandler storeCacheHandler = new CancellableHandler() {

        @Override
        public void handleRegularMessage(Message msg) {
            try {
                if (storeDialog != null) {
                    storeDialog.dismiss();
                }

                finish();
                return;
            } catch (Exception e) {
                showToast(res.getString(R.string.err_store));

                Log.e("cgeopopup.storeCacheHandler: " + e.toString());
            }

            if (storeDialog != null) {
                storeDialog.dismiss();
            }
            init();
        }
    };
    private final Handler dropCacheHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            try {
                if (dropDialog != null) {
                    dropDialog.dismiss();
                }

                finish();
                return;
            } catch (Exception e) {
                showToast(res.getString(R.string.err_drop));

                Log.e("cgeopopup.dropCacheHandler: " + e.toString());
            }

            if (dropDialog != null) {
                dropDialog.dismiss();
            }
            init();
        }
    };

    public CachePopup() {
        super("c:geo-cache-info", R.layout.popup);
        popupIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);

        context.startActivity(popupIntent);
    }

    public static void startActivityAllowTarget(final Activity activity, final String geocode) {
        final Intent popupIntent = new Intent(activity, CachePopup.class);
        popupIntent.putExtra(Intents.EXTRA_GEOCODE, geocode);

        activity.startActivityForResult(popupIntent, AbstractDialogFragment.REQUEST_CODE_TARGET_INFO);
    }
}

                offlineRefresh.setVisibility(View.VISIBLE);
                offlineRefresh.setEnabled(true);
                offlineRefresh.setOnClickListener(new StoreCache());

                offlineStore.setText(res.getString(R.string.cache_offline_drop));
                offlineStore.setEnabled(true);
                offlineStore.setOnClickListener(new DropCache());
            } else {
                offlineText.setText(res.getString(R.string.cache_offline_not_ready));


                offlineStore.setText(res.getString(R.string.cache_offline_store));
                offlineStore.setEnabled(true);
                offlineStore.setOnClickListener(new StoreCache());
            }
        } catch (Exception e) {
            Log.e("cgeopopup.init: " + e.toString());
        }
    }

    @Override
        init();
    }

    private class StoreCache implements View.OnClickListener {

        @Override
        public void onClick(View arg0) {
            if (dropDialog != null && dropDialog.isShowing()) {
                showToast("Still removing this cache.");
                return;
            }

            storeDialog = ProgressDialog.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true);
            storeDialog.setCancelable(false);
            final Thread thread = new StoreCacheThread(storeCacheHandler);
            thread.start();
        }
    }

    private class StoreCacheThread extends Thread {

        final private CancellableHandler handler;

        public StoreCacheThread(final CancellableHandler handler) {
        }
    }

    private class DropCache implements View.OnClickListener {

        @Override
        public void onClick(View arg0) {
            if (storeDialog != null && storeDialog.isShowing()) {
                showToast("Still saving this cache.");
                return;
            }

            dropDialog = ProgressDialog.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true);
            dropDialog.setCancelable(false);
            final Thread thread = new DropCacheThread(dropCacheHandler);
            thread.start();
        }
    }


<MSG> Merge pull request #1507 from campbeb/fix1435try2

Fix #1435 by refactoring the save/refresh/drop architecture
<DFF> @@ -1,5 +1,6 @@
 package cgeo.geocaching;
 
+import cgeo.geocaching.activity.Progress;
 import cgeo.geocaching.apps.cache.navi.NavigationAppFactory;
 import cgeo.geocaching.geopoint.Geopoint;
 import cgeo.geocaching.ui.CacheDetailsCreator;
@@ -8,7 +9,6 @@ import cgeo.geocaching.utils.Log;
 
 import org.apache.commons.lang3.StringUtils;
 
-import android.app.ProgressDialog;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -20,54 +20,48 @@ import android.widget.LinearLayout;
 import android.widget.TextView;
 
 public class CachePopup extends AbstractPopupActivity {
-    private ProgressDialog storeDialog = null;
-    private ProgressDialog dropDialog = null;
-    private final CancellableHandler storeCacheHandler = new CancellableHandler() {
+    private final Progress progress = new Progress();
 
+    private class StoreCacheHandler extends CancellableHandler {
         @Override
         public void handleRegularMessage(Message msg) {
-            try {
-                if (storeDialog != null) {
-                    storeDialog.dismiss();
-                }
-
-                finish();
-                return;
-            } catch (Exception e) {
-                showToast(res.getString(R.string.err_store));
-
-                Log.e("cgeopopup.storeCacheHandler: " + e.toString());
+            if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) {
+                updateStatusMsg((String) msg.obj);
+            } else {
+                init();
             }
+        }
 
-            if (storeDialog != null) {
-                storeDialog.dismiss();
-            }
-            init();
+        private void updateStatusMsg(final String msg) {
+            progress.setMessage(res.getString(R.string.cache_dialog_offline_save_message)
+                    + "\n\n"
+                    + msg);
         }
-    };
-    private final Handler dropCacheHandler = new Handler() {
+    }
 
+    private class DropCacheHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
-            try {
-                if (dropDialog != null) {
-                    dropDialog.dismiss();
-                }
-
-                finish();
-                return;
-            } catch (Exception e) {
-                showToast(res.getString(R.string.err_drop));
+            init();
+        }
+    }
 
-                Log.e("cgeopopup.dropCacheHandler: " + e.toString());
+    private class RefreshCacheHandler extends CancellableHandler {
+        @Override
+        public void handleRegularMessage(Message msg) {
+            if (UPDATE_LOAD_PROGRESS_DETAIL == msg.what && msg.obj instanceof String) {
+                updateStatusMsg((String) msg.obj);
+            } else {
+                init();
             }
+        }
 
-            if (dropDialog != null) {
-                dropDialog.dismiss();
-            }
-            init();
+        private void updateStatusMsg(final String msg) {
+            progress.setMessage(res.getString(R.string.cache_dialog_refresh_message)
+                    + "\n\n"
+                    + msg);
         }
-    };
+    }
 
     public CachePopup() {
         super("c:geo-cache-info", R.layout.popup);
@@ -122,11 +116,11 @@ public class CachePopup extends AbstractPopupActivity {
 
                 offlineRefresh.setVisibility(View.VISIBLE);
                 offlineRefresh.setEnabled(true);
-                offlineRefresh.setOnClickListener(new StoreCache());
+                offlineRefresh.setOnClickListener(new RefreshCacheClickListener());
 
                 offlineStore.setText(res.getString(R.string.cache_offline_drop));
                 offlineStore.setEnabled(true);
-                offlineStore.setOnClickListener(new DropCache());
+                offlineStore.setOnClickListener(new DropCacheClickListener());
             } else {
                 offlineText.setText(res.getString(R.string.cache_offline_not_ready));
 
@@ -137,11 +131,14 @@ public class CachePopup extends AbstractPopupActivity {
 
                 offlineStore.setText(res.getString(R.string.cache_offline_store));
                 offlineStore.setEnabled(true);
-                offlineStore.setOnClickListener(new StoreCache());
+                offlineStore.setOnClickListener(new StoreCacheClickListener());
             }
         } catch (Exception e) {
             Log.e("cgeopopup.init: " + e.toString());
         }
+
+        // cache is loaded. remove progress-popup if any there
+        progress.dismiss();
     }
 
     @Override
@@ -151,24 +148,21 @@ public class CachePopup extends AbstractPopupActivity {
         init();
     }
 
-    private class StoreCache implements View.OnClickListener {
-
+    private class StoreCacheClickListener implements View.OnClickListener {
         @Override
         public void onClick(View arg0) {
-            if (dropDialog != null && dropDialog.isShowing()) {
-                showToast("Still removing this cache.");
+            if (progress.isShowing()) {
+                showToast(res.getString(R.string.err_detail_still_working));
                 return;
             }
 
-            storeDialog = ProgressDialog.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true);
-            storeDialog.setCancelable(false);
-            final Thread thread = new StoreCacheThread(storeCacheHandler);
-            thread.start();
+            final StoreCacheHandler storeCacheHandler = new StoreCacheHandler();
+            progress.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_save_title), res.getString(R.string.cache_dialog_offline_save_message), true, storeCacheHandler.cancelMessage());
+            new StoreCacheThread(storeCacheHandler).start();
         }
     }
 
     private class StoreCacheThread extends Thread {
-
         final private CancellableHandler handler;
 
         public StoreCacheThread(final CancellableHandler handler) {
@@ -182,19 +176,44 @@ public class CachePopup extends AbstractPopupActivity {
         }
     }
 
-    private class DropCache implements View.OnClickListener {
+    private class RefreshCacheClickListener implements View.OnClickListener {
+        public void onClick(View arg0) {
+            if (progress.isShowing()) {
+                showToast(res.getString(R.string.err_detail_still_working));
+                return;
+            }
+
+            final RefreshCacheHandler refreshCacheHandler = new RefreshCacheHandler();
+            progress.show(CachePopup.this, res.getString(R.string.cache_dialog_refresh_title), res.getString(R.string.cache_dialog_refresh_message), true, refreshCacheHandler.cancelMessage());
+            new RefreshCacheThread(refreshCacheHandler).start();
+        }
+    }
+
+    private class RefreshCacheThread extends Thread {
+        final private CancellableHandler handler;
+
+        public RefreshCacheThread(final CancellableHandler handler) {
+            this.handler = handler;
+        }
+
+        @Override
+        public void run() {
+            cache.refresh(cache.getListId(), handler);
+            handler.sendEmptyMessage(0);
+        }
+    }
 
+    private class DropCacheClickListener implements View.OnClickListener {
         @Override
         public void onClick(View arg0) {
-            if (storeDialog != null && storeDialog.isShowing()) {
-                showToast("Still saving this cache.");
+            if (progress.isShowing()) {
+                showToast(res.getString(R.string.err_detail_still_working));
                 return;
             }
 
-            dropDialog = ProgressDialog.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true);
-            dropDialog.setCancelable(false);
-            final Thread thread = new DropCacheThread(dropCacheHandler);
-            thread.start();
+            final DropCacheHandler dropCacheHandler = new DropCacheHandler();
+            progress.show(CachePopup.this, res.getString(R.string.cache_dialog_offline_drop_title), res.getString(R.string.cache_dialog_offline_drop_message), true, null);
+            new DropCacheThread(dropCacheHandler).start();
         }
     }
 

Merge pull request #1507 from campbeb/fix1435try2