0

I have added a dialog fragment with a date picker to MainActivity and it works fine. I now want to pass the date selected with the date picker to a new activity which is called by MainActivity. So I use an intent to communicate between MainActivity and the new activity.

But how can I actually pass the date chosen from the dialog fragment to the MainActivity?

public class DatePickerFragment extends DialogFragment
                            implements DatePickerDialog.OnDateSetListener {
public static String formattedDate = "com.example.myfirstapp.DATEOB";

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    // Use the current date as the default date in the picker
    final Calendar c = Calendar.getInstance();
    int year = c.get(Calendar.YEAR);
    int month = c.get(Calendar.MONTH);
    int day = c.get(Calendar.DAY_OF_MONTH); 

    // Create a new instance of DatePickerDialog and return it
    return new DatePickerDialog(getActivity(), this, year, month, day);
}

@Override
public void onDateSet(DatePicker view, int year, int month, int day) {

    Calendar c = Calendar.getInstance();
    c.set(year, month, day);
OneTwo
  • 2,291
  • 6
  • 33
  • 55
  • possible duplicate of [How do I pass data between activities in Android?](http://stackoverflow.com/questions/2091465/how-do-i-pass-data-between-activities-in-android) – Xaver Kapeller Jul 03 '14 at 16:30
  • No I know how to pass data between activities but not between a fragment and an activity – OneTwo Jul 03 '14 at 16:32
  • Using a listener interface would be best practice. Casting the `Activity` like @GiladHaimov suggests is a bad idea. Doing so would defy the purpose of a `Fragment` as it could only be used in that one `Activity`. – Xaver Kapeller Jul 03 '14 at 16:36

4 Answers4

10

The best practice solution to pass data between a Fragment and an Activity is to use the listener pattern.


Implementing the listener pattern in the Fragment

First we need to define an interface. We add a method called onDateSet() with a Date parameter. It will be used to pass the Date back to the Activity:

public interface DatePickerFragmentListener {
    public void onDateSet(Date date);
}

I recommend you nest this interface inside of the DatePickerFragment like this:

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

    public interface DatePickerFragmentListener {
        public void onDateSet(Date date);
    }

    ...
}

We need to add a member variable to the DatePickerFragment to hold the reference to the listener. We also need getter and setter methods for the listener and a notify method to safely call the listener:

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

    private DatePickerFragmentListener datePickerListener;
    public interface DatePickerFragmentListener {
        public void onDateSet(Date date);
    }

    public DatePickerFragmentListener getDatePickerListener() {
        return this.datePickerListener;
    }

    public void setDatePickerListener(DatePickerFragmentListener listener) {
        this.datePickerListener = listener;
    }

    protected void notifyDatePickerListener(Date date) {
        if(this.datePickerListener != null) {
            this.datePickerListener.onDateSet(date);
        }
    }

    ...
}

It is best practice to use a static factory method to create new Fragment instances. One of the many benefits of doing this besides just convenience is that you can define a method that sets up the Fragment correctly - for example setting listeners, passing values to the Fragment etc. - and you don't risk forgetting something or mixing something up later on. In our case it needs to set the DatePickerFragmentListener:

public class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

    public static DatePickerFragment newInstance(DatePickerFragmentListener listener) {
        DatePickerFragment fragment = new DatePickerFragment();
        fragment.setDatePickerListener(listener);
        return fragment;
    }

    ...
}

Now the only thing still missing is that we need to call notifyDatePickerListener() in the callback of the DatePicker in the DatePickerFragment:

@Override
public void onDateSet(DatePicker view, int year, int month, int day) {
    Calendar c = Calendar.getInstance();
    c.set(year, month, day);
    Date date = c.getTime();

    // Here we call the listener and pass the date back to it.
    notifyDatePickerListener(date);
} 

Using it in your Activity

In your Activity we just need to call the newInstance() method we added to create a new properly set up DatePickerFragment. We also need to pass a DatePickerFragmentListener into newInstance(). I recommend you let your Activity implement the DatePickerFragmentListener interface:

public class MainActivity extends Activity implements DatePickerFragmentListener {

    ...

    @Override
    public void onDateSet(Date date) {
        // This method will be called with the date from the `DatePicker`.
    }
}

You just have to create a new instance of your DatePickerFragment using the newInstance() method and pass in the Activity to make this work:

DatePickerFragment fragment = DatePickerFragment.newInstance(this);

And that's it! Implementing it this way might be 10 lines of code more, but it is a 100 times better solution.


I tested everything and it is working perfectly. I hope I could help you and if you have any other questions feel free to ask!

Xaver Kapeller
  • 49,491
  • 11
  • 98
  • 86
  • is the listener pattern you recommend above still considered best practice for passing data from Fragment to an Activity? – AJW Oct 24 '18 at 02:02
0

Put extras to the intent:

Intent i = new Intent(getApplicationContext(), MyOtherActivity.class);
intent.putExtra("EXTRA_DATA", myDataVariable);
intent.putExtra("EXTRA_DATA_2", myOtherDataVariable);
/// [...]
startActivity(i)

Into the other activity, retrieve the data like this:

Bundle b = getIntent().getExtras();
if (b != null) {
    Int myValue = b.getInt("EXTRA_DATA");
}

Be careful to get the correct data type: if you put an integer in the first activity, use getInt in the other one; if you put a string, use getString, etc.

dentex
  • 3,223
  • 4
  • 28
  • 47
0

The simplest way to pass data from fragment to containing activity is to call

fragment.getActivity()

All fragments, DialogFragment included, have this method.

After casting to actual activity class (say: MainActivity) you will be able to activate all public methods within activity. Assuming you called your date-set handler method onDateSet:

class DatePickerFragment  { 

   @Override
   public void onDateSet(DatePicker view, int year, int month, int day) {
       .....
       ((MainActivity)getActivity()).onDateSet(calendar); // <---- pass value to activity
  }
}

Where the MainActivity implementation will be:

class MainActivity {

     private Calendar selectedDate;

     public onDateSet(Calendar newDate) {
           selectedDate = newDate;
     }
}

As for passing data from one activity to another, just pack it into the activation intent

Intent i = new Intent(context, AnotherActivity.class);
i.putExtra("Year", 2014);
i.putExtra("Month", 11);
....
startActivity(i);
Gilad Haimov
  • 5,767
  • 2
  • 26
  • 30
0

I tried this and it worked on my project. after picked date, ı took the date via a button to use on another activity.

public void onclickname (){
Intent intentname = new Intent(currentjava.this, otherjava.class);
EditText edittext =(EditText) findViewById(R.id.edittextid);
Editable namedsomething=edittext.getText();
String anyname=namedsomething.toString();
Bundle bundlename= new Bundle();
bundlename.putString("aname", anyname);
startActivity(intentname);

on intended java you can call like this

Bundle bundlename=getIntent().getExtras();
String astring=bundle.getString("aname");