Android “Best Practice” returning values from a dialog

后端 未结 6 1652
闹比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:01

    I will explain one solution with the example of two fragments. Imagine there is a SimpleFragment which has just one text field to render a date. Then there is a DatePickerFragment which allows to choose a particular date. What I want is that the DatePickerFragment passes the date value back to the calling SimpleFragment whenever the user confirms her selection.

    SimpleFragment

    So, first of all we start the DatePickerFragment from within the SimpleFragment:

    private DateTime mFavoriteDate; // Joda-Time date
    
    private void launchDatePicker() {
        DatePickerFragment datePickerFragment = new DatePickerFragment();
        Bundle extras = new Bundle();
        // Pass an initial or the last value for the date picker
        long dateInMilliSeconds = mFavoriteDate.getMillis();
        extras.putLong(BundleKeys.LAST_KNOWN_DATE, dateInMilliSeconds);
        datePickerFragment.setArguments(extras);
        datePickerFragment.setTargetFragment(this, SIMPLE_FRAGMENT_REQUEST_CODE);
        datePickerFragment.show(getActivity().getSupportFragmentManager(),
                DatePickerFragment.FRAGMENT_TAG);
    }
    

    DatePickerFragment

    In the dialog fragment we prepare to pass back the selected date when the user hits the positive button:

    public static final String DATE_PICKED_INTENT_KEY = "DATE_PICKED_INTENT_KEY";
    public static final int DATE_PICKED_RESULT_CODE = 123;
    
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // ...
        Long dateInMilliSeconds = getArguments().getLong(BundleKeys.LAST_KNOWN_DATE);
        DateTime date = new DateTime(dateInMilliSeconds);
        initializePickerUiControl(date);
    
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(activity);
        dialogBuilder
            .setPositiveButton(R.string.date_picker_positive, (dialog, which) -> {
                // Pass date to caller
                passBackDate();
            })
            .setNegativeButton(R.string.date_picker_negative, (dialog, which) -> {
                // Nothing to do here
            });
        return dialogBuilder.create();
    }
    
    private void passBackDate() {
        DateTime dateTime = getDateTimeFromPickerControl();
        Intent intent = new Intent();
        intent.putExtra(DATE_PICKED_INTENT_KEY, dateTime.getMillis());
        getTargetFragment().onActivityResult(
                getTargetRequestCode(), DATE_PICKED_RESULT_CODE, intent);
    }
    

    SimpleFragment

    Back in the requesting fragment we consume what has been passed back by the dialog:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == SIMPLE_FRAGMENT_REQUEST_CODE &&
                resultCode == DatePickerFragment.DATE_PICKED_RESULT_CODE) {
            long datePickedInMilliseconds = data.getLongExtra(
                    DatePickerFragment.DATE_PICKED_INTENT_KEY, 0);
            mFavoriteDate = new DateTime(datePickedInMilliseconds);
            updateFavoriteDateTextView();
        }
        else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }
    

    References to mattpic who gave an excellent answer before.

提交回复
热议问题