2012-12-26 7 views
29

Ich habe ein DialogFragment, das einen DatePickerDialog erstellt. Ich verwende eine statische Methode newInstance, um die Anfangswerte festzulegen, um den leeren Standardkonstruktor zu verwenden. Wie soll ich den Hörer einstellen? Nach der Bildschirmdrehung, wenn Sie auf die Schaltfläche "Fertig" klicken, macht der Listener nichts, da er nicht existiert.DialogFragment - Beibehalten des Listeners nach der Bildschirmrotation

public class DatePickerFragment extends DialogFragment { 
    public static final String ARG_YEAR = "year"; 
    public static final String ARG_MONTH = "month"; 
    public static final String ARG_DAY = "day"; 

    private OnDateSetListener listener_; 

    public static DatePickerFragment newInstance(OnDateSetListener listener, int year, int month, int day) { 
     final DatePickerFragment date_picker = new DatePickerFragment(); 
     date_picker.setListener(listener); 

     final Bundle arguments = new Bundle(); 
     arguments.putInt(ARG_YEAR, year); 
     arguments.putInt(ARG_MONTH, month); 
     arguments.putInt(ARG_DAY, day); 
     date_picker.setArguments(arguments); 

     return date_picker; 
    } 

    private void setListener(OnDateSetListener listener) { 
     listener_ = listener; 
    } 

    @Override 
    public Dialog onCreateDialog(Bundle saved_instance_state) { 
     final Bundle arguments = getArguments(); 
     final int year = arguments.getInt(ARG_YEAR); 
     final int month = arguments.getInt(ARG_MONTH); 
     final int day = arguments.getInt(ARG_DAY); 

     return new DatePickerDialog(getActivity(), listener_, year, month, day); 
    } 
} 

Antwort

55

Doch wie soll ich den Hörer setzen?

Sie aktualisieren die Zuhörer Referenz in der onCreate Methode des Activity:

private OnDateSetListener mOds = new OnDateSetListener() { 

    @Override 
    public void onDateSet(DatePicker view, int year, int monthOfYear, 
      int dayOfMonth) { 
      // do important stuff 
    } 
}; 

und in der onCreate Methode:

if (savedInstanceState != null) { 
    DatePickerFragment dpf = (DatePickerFragment) getSupportFragmentManager() 
      .findFragmentByTag("theTag?"); 
    if (dpf != null) { 
     dpf.setListener(mOds); 
    } 
} 
+1

Große Lösung dokumentiert! Es funktionierte einwandfrei. Danke, @Luksprog. –

+0

Die richtige Lösung :) –

+1

+1, auch für die Klärung, ist die wichtige Sache, das Tag des Dialogfragments zu verwenden, um den Zuhörer wieder anzubringen. Dieses Tag wird im zweiten Argument der 'show' Methode des Dialogfragments angegeben. – rekaszeru

2

Die Antwort von Luksprog richtig ist, ich will nur weisen Sie darauf hin, der Schlüssel der Lösung ist die Funktion findFragmentByTag(). Da die Aktivität auch nach der Bildschirmdrehung neu erstellt wird, können Sie die Setter-Funktion ihrer Member-Fragment-Variable nicht aufrufen, stattdessen sollten Sie die alte Fragment-Instanz mit dieser Funktion finden.

Btw, das Tag ist der zweite Parameter, wenn Sie DialogFragment.show() aufrufen.

+0

Danke, eine gute Beschreibung. – CoolMind

6

Meiner Meinung nach gibt es einen effizienteren Weg, dies zu tun, mit dem Fragment-Lebenszyklus. Sie können die Fragment-Lifecycle-Rückrufe onAttach() und onDetach() verwenden, um automatisch die Tätigkeit als Zuhörer zu werfen wie so:

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    try { 
     _listener = (OnDateSetListener)activity; 
    } catch(ClassCastException e) { 
     // check if _listener is null before using, 
     // or throw new ClassCastException("hosting activity must implement OnDateSetListener"); 
    } 
} 

@Override 
public void onDetach() { 
    super.onDetach(); 
    _listener = null; 
} 

Diese Technik offiziell here

+0

Ja, aber auf diese Weise können Sie die gleiche Klasse (sagen wir ein DialogFragment) nicht mehr in einer Aktivität mit verschiedenen Listenern verwenden ... – ARLabs

+1

Warum nicht? Implementieren Sie einfach die gewünschte Listener-Schnittstelle für die Aktivität und wandeln Sie sie im DialogFragment in verschiedene Listener-Instanzen um. Wenn Sie einige optionale hinzufügen möchten, können Sie einfach eine komplexere ClassCast-Fehlerbehandlung durchführen. – d370urn3ur

+1

Ich meine, wenn dieselbe Aktivität zwei DialogFragment zweimal verwenden muss und (wie Sie vorgeschlagen haben), erbt Aktivität vom Listener, wenn die Listener-Methode in der Aktivität aufgerufen wird, wissen Sie nicht, was der Fall ist ... I denke, es ist besser, zwei verschiedene Listener-Instanzen zu verwenden (sie können nicht die Aktivität sein). Was ich gesagt habe, beruht auf der Hypothese, dass wir für ein gutes Design zirkuläre Abhängigkeiten vermeiden und das DialogFragment seinen eigenen Listenertyp definiert und die Spezialisierung der Aktivität nicht kennt. – ARLabs