How to handle screen orientation change when progress dialog and background thread active?

前端 未结 28 1278
轮回少年
轮回少年 2020-11-22 07:03

My program does some network activity in a background thread. Before starting, it pops up a progress dialog. The dialog is dismissed on the handler. This all works fine, exc

28条回答
  •  长发绾君心
    2020-11-22 07:43

    This is my solution when I faced it: ProgressDialog is not a Fragment child, so my custom class "ProgressDialogFragment" can extend DialogFragment instead in order to keep the dialog shown for configuration changes.

    import androidx.annotation.NonNull;
    import android.app.Dialog;
    import android.app.ProgressDialog;
    import android.os.Bundle; 
    import androidx.fragment.app.DialogFragment;
    import androidx.fragment.app.FragmentManager;
    
     /**
     * Usage:
     * To display the dialog:
     *     >>> ProgressDialogFragment.showProgressDialogFragment(
     *              getSupportFragmentManager(), 
     *              "fragment_tag", 
     *              "my dialog title", 
     *              "my dialog message");
     *              
     * To hide the dialog
     *     >>> ProgressDialogFragment.hideProgressDialogFragment();
     */ 
    
    
    public class ProgressDialogFragment extends DialogFragment {
    
        private static String sTitle, sMessage;
        private static ProgressDialogFragment sProgressDialogFragment;
    
        public ProgressDialogFragment() {
        }
    
        private ProgressDialogFragment(String title, String message) {
            sTitle = title;
            sMessage = message;
        }
    
    
        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            return ProgressDialog.show(getActivity(), sTitle, sMessage);
        }
    
        public static void showProgressDialogFragment(FragmentManager fragmentManager, String fragmentTag, String title, String message) {
            if (sProgressDialogFragment == null) {
                sProgressDialogFragment = new ProgressDialogFragment(title, message);
                sProgressDialogFragment.show(fragmentManager, fragmentTag);
    
            } else { // case of config change (device rotation)
                sProgressDialogFragment = (ProgressDialogFragment) fragmentManager.findFragmentByTag(fragmentTag); // sProgressDialogFragment will try to survive its state on configuration as much as it can, but when calling .dismiss() it returns NPE, so we have to reset it on each config change
                sTitle = title;
                sMessage = message;
            }
    
        }
    
        public static void hideProgressDialogFragment() {
            if (sProgressDialogFragment != null) {
                sProgressDialogFragment.dismiss();
            }
        }
    }
    

    The challenge was to retain the dialog title & message while screen rotation as they reset to the default empty string, although the dialog still shown

    There are 2 approaches to solve this:

    First approach: Make the activity that utilizes the dialog to retain state during config change in manifest file:

    android:configChanges="orientation|screenSize|keyboardHidden"
    

    This approach is not preferred by Google.

    Second approach: on the activity's onCreate() method, you need to retain your DialogFragment by rebuilding the ProgressDialogFragment again with the title & message as follows if the savedInstanceState is not null:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_deal);
    
     if (savedInstanceState != null) {
          ProgressDialogFragment saveProgressDialog = (ProgressDialogFragment) getSupportFragmentManager()
                  .findFragmentByTag("fragment_tag");
          if (saveProgressDialog != null) {
              showProgressDialogFragment(getSupportFragmentManager(), "fragment_tag", "my dialog title", "my dialog message");
          }
      }
    }
    

提交回复
热议问题