Android “Best Practice” returning values from a dialog

后端 未结 6 1644
闹比i
闹比i 2020-12-07 18:27

What is the \"correct\" way to return the values to the calling activity from a complex custom dialog - say, text fields, date or time picker, a bunch of radio buttons, etc,

6条回答
  •  温柔的废话
    2020-12-07 19:16

    For my MIDI app I needed yes/no/cancel confirmation dialogs, so I first made a general StandardDialog class:

    public class StandardDialog {
    
        import android.app.Activity;
        import android.app.AlertDialog;
        import android.content.DialogInterface;
        import android.os.Handler;
    
        public class StandardDialog {
        public static final int dlgResultOk         = 0;
        public static final int dlgResultYes        = 1;
        public static final int dlgResultNo         = 2;
        public static final int dlgResultCancel     = 3;
    
        public static final int dlgTypeOk           = 10;
        public static final int dlgTypeYesNo        = 11;
        public static final int dlgTypeYesNoCancel  = 12;
    
        private Handler mResponseHandler;
        private AlertDialog.Builder mDialogBuilder;
        private int mDialogId;
    
        public StandardDialog(Activity parent, 
                              Handler reponseHandler, 
                              String title, 
                              String message, 
                              int dialogType, 
                              int dialogId) {
    
            mResponseHandler = reponseHandler;
            mDialogId = dialogId;
            mDialogBuilder = new AlertDialog.Builder(parent);
            mDialogBuilder.setCancelable(false);
            mDialogBuilder.setTitle(title);
            mDialogBuilder.setIcon(android.R.drawable.ic_dialog_alert);
            mDialogBuilder.setMessage(message);
            switch (dialogType) {
            case dlgTypeOk:
                mDialogBuilder.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        mResponseHandler.sendEmptyMessage(mDialogId + dlgResultOk);
                    }
                });         
                break;
    
            case dlgTypeYesNo:
            case dlgTypeYesNoCancel:
                mDialogBuilder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        mResponseHandler.sendEmptyMessage(mDialogId + dlgResultYes);
                    }
                });         
                mDialogBuilder.setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        mResponseHandler.sendEmptyMessage(mDialogId + dlgResultNo);
                    }
                });         
                if (dialogType == dlgTypeYesNoCancel) {
                    mDialogBuilder.setNeutralButton("Cancel", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            mResponseHandler.sendEmptyMessage(mDialogId + dlgResultCancel);
                        }
                    });         
                }
                break;
            }
            mDialogBuilder.show();
        }
    }
    

    Next, in my main activity I already had a message handler for the UI updates from other threads, so I just added code for processing messages from the dialogs. By using a different dialogId parameter when I instantiate the StandardDialog for various program functions, I can execute the proper code to handle the yes/no/cancel responses to different questions. This idea can be extended for complex custom dialogs by sending a Bundle of data though this is much slower than a simple integer message.

    private Handler uiMsgHandler = new Handler() {
    
        @Override
        public void handleMessage(Message msg) {
            if (msg != null) {
    
                // {Code to check for other UI messages here}
    
                // Check for dialog box responses
                if (msg.what == (clearDlgId + StandardDialog.dlgResultYes)) {
                    doClearDlgYesClicked();
                }
                else if (msg.what == (recordDlgId + StandardDialog.dlgResultYes)) {
                    doRecordDlgYesClicked();
                }
                else if (msg.what == (recordDlgId + StandardDialog.dlgResultNo)) {
                    doRecordDlgNoClicked();
                }
            }
        }
    };
    

    Then all I need to do is define the do{Whatever}() methods in the activity. To bring up a dialog, as an example I have a method responding to a "clear recorded MIDI events" button and confirm it as follows:

    public void onClearBtnClicked(View view) {
        new StandardDialog(this, uiMsgHandler, 
            getResources().getString(R.string.dlgTitleClear),
            getResources().getString(R.string.dlgMsgClear), 
            StandardDialog.dlgTypeYesNo, clearDlgId);
    }
    

    clearDlgId is defined as a unique integer elsewhere. This method makes a Yes/No dialog pop up in front of the activity, which loses focus until the dialog closes, at which time the activity gets a message with the dialog result. Then the message handler calls the doClearDlgYesClicked() method if the "Yes" button was clicked. (I didn't need a message for the "No" button since no action was needed in that case).

    Anyway, this method works for me, and makes it easy to pass results back from a dialog.

提交回复
热议问题