2012-12-26 40 views
29

我有一個DialogFragment創建DatePickerDialog。我正在使用名爲newInstance的靜態方法來設置初始值,以便使用默認的空構造函數。但是,我該如何設置聽衆?在屏幕旋轉後,當點擊「完成」按鈕時,監聽器不會執行任何操作,因爲它不存在。DialogFragment - 屏幕旋轉後保留偵聽器

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); 
    } 
} 

回答

55

但是,我怎麼設置監聽器?

您更新在onCreate方法Activity的聽衆參考:

private OnDateSetListener mOds = new OnDateSetListener() { 

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

,並在onCreate方法:以

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

的最佳解決方案!它工作完美無瑕。謝謝你,@Luksprog。 –

+0

正確的解決方案:) –

+1

+1,同樣爲了澄清,重要的是使用對話框片段的標籤重新應用偵聽器。這個標籤是在對話框片段show的方法的第二個參數中指定的。 – rekaszeru

2

Luksprog的答案是正確的,我只是想指出,解決方案的關鍵是findFragmentByTag()函數。由於活動將在屏幕旋轉後重新創建,因此您無法調用其成員Fragment變量的setter函數,而應該使用此函數查找舊的片段實例。

順便說一句,標記是您調用DialogFragment.show()時的第二個參數。

+0

謝謝,很好的描述。 – CoolMind

6

在我看來,有一個更有效的方式來做到這一點,使用片段生命週期。您可以使用片段生命週期回調onAttach()onDetach()自動施放活動的監聽器,如下:

@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; 
} 

這種技術被正式記錄在案here

+0

是的,但通過這種方式,您不能在具有不同聽衆的活動中使用同一個類(讓我說一個DialogFragment)... – ARLabs

+1

爲什麼不能?只需在Activity上實現您想要的任何偵聽器接口,並將其轉換爲DialogFragment中的不同偵聽器實例即可。如果你想使一些可選的,你可以只是有更復雜的ClassCast錯誤處理。 – d370urn3ur

+1

我的意思是,如果同一個Activity需要使用兩次相同的DialogFragment並且(如您所建議的那樣),那麼Activity會從偵聽器繼承,當調用活動中的偵聽器方法時,您不知道是哪種情況...... I認爲使用兩個不同的偵聽器實例會更好(它們不能是活動)。我說的依賴於假設,爲了良好的設計,我們避免了循環依賴,DialogFragment定義了它自己的偵聽器類型,並且它不知道活動專用。 – ARLabs