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

前端 未结 28 1836
轮回少年
轮回少年 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:50

    I came up with a rock-solid solution for these issues that conforms with the 'Android Way' of things. I have all my long-running operations using the IntentService pattern.

    That is, my activities broadcast intents, the IntentService does the work, saves the data in the DB and then broadcasts sticky intents. The sticky part is important, such that even if the Activity was paused during during the time after the user initiated the work and misses the real time broadcast from the IntentService we can still respond and pick up the data from the calling Activity. ProgressDialogs can work with this pattern quite nicely with onSaveInstanceState().

    Basically, you need to save a flag that you have a progress dialog running in the saved instance bundle. Do not save the progress dialog object because this will leak the entire Activity. To have a persistent handle to the progress dialog, I store it as a weak reference in the application object. On orientation change or anything else that causes the Activity to pause (phone call, user hits home etc.) and then resume, I dismiss the old dialog and recreate a new dialog in the newly created Activity.

    For indefinite progress dialogs this is easy. For progress bar style, you have to put the last known progress in the bundle and whatever information you're using locally in the activity to keep track of the progress. On restoring the progress, you'll use this information to re-spawn the progress bar in the same state as before and then update based on the current state of things.

    So to summarize, putting long-running tasks into an IntentService coupled with judicious use of onSaveInstanceState() allows you to efficiently keep track of dialogs and restore then across the Activity life-cycle events. Relevant bits of Activity code are below. You'll also need logic in your BroadcastReceiver to handle Sticky intents appropriately, but that is beyond the scope of this.

    public void doSignIn(View view) {
        waiting=true;
        AppClass app=(AppClass) getApplication();
        String logingon=getString(R.string.signon);
        app.Dialog=new WeakReference(ProgressDialog.show(AddAccount.this, "", logingon, true));
        ...
    }
    
    @Override
    protected void onSaveInstanceState(Bundle saveState) {
        super.onSaveInstanceState(saveState);
        saveState.putBoolean("waiting",waiting);
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(savedInstanceState!=null) {
            restoreProgress(savedInstanceState);    
        }
        ...
    }
    
    private void restoreProgress(Bundle savedInstanceState) {
        waiting=savedInstanceState.getBoolean("waiting");
        if (waiting) {
            AppClass app=(AppClass) getApplication();
            ProgressDialog refresher=(ProgressDialog) app.Dialog.get();
            refresher.dismiss();
            String logingon=getString(R.string.signon);
            app.Dialog=new WeakReference(ProgressDialog.show(AddAccount.this, "", logingon, true));
        }
    }
    

提交回复
热议问题