14

में चर्चा के अनुसार DialogFragment सिस्टम का उपयोग करने के लिए, वर्तमान में Activity.showDialog(DIALOG_ID); का उपयोग करके मैं अपने संवाद माइग्रेट कर रहा हूं।ओरिएंटेशन चेंज पर डायलॉगफ्रैगमेंट कॉलबैक

यहाँ है एक सरल संवाद के कुछ उदाहरण कोड:

public class DialogTest extends DialogFragment { 

public interface DialogTestListener { 
    public void onDialogPositiveClick(DialogFragment dialog); 
} 

// Use this instance of the interface to deliver action events 
static DialogTestListener mListener; 

public static DialogTest newInstance(Activity activity, int titleId, int messageId) { 
    udateListener(activity); 
    DialogTest frag = new DialogTest(); 
    Bundle args = new Bundle(); 
    args.putInt("titleId", titleId); 
    args.putInt("messageId", messageId); 
    frag.setArguments(args); 
    return frag; 
} 

public static void udateListener(Activity activity) { 
    try { 
     // Instantiate the NoticeDialogListener so we can send events with it 
     mListener = (DialogTestListener) activity; 
    } catch (ClassCastException e) { 
     // The activity doesn't implement the interface, throw exception 
     throw new ClassCastException(activity.toString() + " must implement DialogTestListener"); 
    } 
} 


@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) { 
    int titleId = getArguments().getInt("titleId"); 
    int messageId = getArguments().getInt("messageId"); 

    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
    // dialog title 
    builder.setTitle(titleId); 
    // dialog message 
    builder.setMessage(messageId); 

    // dialog negative button 
    builder.setNegativeButton("No", new OnClickListener() { 
       public void onClick(DialogInterface dialog, int id) {}}); 
    // dialog positive button 
    builder.setPositiveButton("Yes", new OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      mListener.onDialogPositiveClick(DialogTest.this); 
     }}); 

    // create the Dialog object and return it 
    return builder.create(); 
}} 

वहाँ एक सवाल है कि मेरे विकास के दौरान पैदा हुई जब कॉलबैक का उपयोग करके किसी घटना वापस गतिविधि/टुकड़ा है कि संवाद खोला करने के लिए वितरित करने के लिए है और यहां कुछ गतिविधि कोड इसे कॉल कर रहे हैं:

public class SomeActivity extends FragmentActivity implements DialogTestListener { 
private EditText mUserName; 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    // setup ui 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.ui_user_edit); 
    // name input 
    mUserName = (EditText) findViewById(R.id.userEdit_editTextName); 
} 

@Override 
public void onDialogPositiveClick(DialogFragment dialog) { 
    Log.d(TAG, this.toString()); 
    mUserName.setText(mUserName.getText() + "1"); 
} 

private void showDialog() { 
    DialogTest test = DialogTest.newInstance(SomeActivity.this, R.string.someTitleText, R.string.someMessageText); 
    test.show(getSupportFragmentManager(), "testDialog"); 
}} 

कोड आप जो संदर्भ देखते हैं, वह काफी है। समस्या यह है कि, जब आप एक अभिविन्यास परिवर्तन करते हैं, जब एक संवाद दिखाया जाता है, तो यह अपेक्षित काम करना बंद कर देता है -> गतिविधि जीवन चक्र के कारण, गतिविधि और संवाद दोनों पुनर्निर्माण होते हैं, और संवाद में अब उचित नहीं है नई पुनर्निर्मित गतिविधि के संदर्भ में। ऐसा करने से

@Override 
protected void onResume() { 
    super.onResume(); 
    DialogTest.udateListener(this); 
} 

, मैं अपेक्षित व्यवहार मिलता है, और संवाद नई पुनर्निर्माण गतिविधि के लिए वापस घटनाओं भेजता है एक ओरिएंटेशन परिवर्तन हुआ:

मैं onResume विधि मेरी activitys के लिए निम्न कोड गयी।

मेरा प्रश्न है: डायलॉगफ्रैगमेंट के बीच कॉलबैक को संभालने के लिए 'सर्वोत्तम अभ्यास' क्या है जो एक अभिविन्यास परिवर्तन के दौरान फ्रैगमेंट एक्टिविटी द्वारा खोला गया था?

सादर

+0

लगता है जैसे आप एक कई टुकड़े टुकड़े गिर गए हैं। मुझे आपके जैसा ही समस्या थी और मैं इस उत्कृष्ट आलेख को पढ़ने के दौरान इसे ठीक करने में सक्षम था: http://code.hootsuite.com/orientation-changes-on-android/। –

उत्तर

6

हाँ, यह एक आम जाल है जो मैं हर समय अपने आप में गिर रहा हूं। सबसे पहले मुझे यह कहना है कि DialogTest.udateListener()onResume() में कॉल करने का आपका समाधान मेरे लिए बिल्कुल उपयुक्त लगता है।

protected void onReceiveResult(int resultCode, Bundle resultData) { 
    if (getActivity() != null){ 
     // Handle result 
    } 
} 

चेक बाहर ResultReceiver doesn't survire to screen rotation के लिए:

public class DialogTest extends DialogFragment { 

public static DialogTest newInstance(ResultReceiver receiver, int titleId, int messageId) { 
    DialogTest frag = new DialogTest(); 
    Bundle args = new Bundle(); 
    args.putParcelable("receiver", receiver); 
    args.putInt("titleId", titleId); 
    args.putInt("messageId", messageId); 
    frag.setArguments(args); 
    return frag; 
} 

@Override 
public Dialog onCreateDialog(Bundle savedInstanceState) { 
    int titleId = getArguments().getInt("titleId"); 
    int messageId = getArguments().getInt("messageId"); 
    ResultReceiver receiver = getArguments().getParcelable("receiver"); 

    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
    // dialog title 
    builder.setTitle(titleId); 
    // dialog message 
    builder.setMessage(messageId); 

    // dialog negative button 
    builder.setNegativeButton("No", new OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      receiver.sendResult(Activity.RESULT_CANCEL, null); 
     }}); 
    // dialog positive button 
    builder.setPositiveButton("Yes", new OnClickListener() { 
     public void onClick(DialogInterface dialog, int id) { 
      receiver.sendResult(Activity.RESULT_OK, null); 
     }}); 

    // create the Dialog object and return it 
    return builder.create(); 
}} 

तो फिर तुम इस तरह रिसीवर में सब कुछ संभाल कर सकते हैं:

एक वैकल्पिक तरीका एक ResultReceiver जो एक Parcelable के रूप में श्रृंखलाबद्ध किया जा सकता है उपयोग करने के लिए किया जाएगा अधिक जानकारी। तो अंत में आपको शायद के साथ ResultReceiver को फिर से रिवायर करने की आवश्यकता है।केवल अंतर यह है कि आप DialogFragment से Activity को रद्द कर देते हैं।

+0

Thx! एक बार मुझे कुछ गतिविधि <-> डायलॉग फ्रैगमेंट डिकूप्लिंग की आवश्यकता होने पर, मैं 'ऑनर्यूम()' समाधान का उपयोग करूंगा, मुझे परिणाम रिसीवर पर एक नज़र डालेंगी। – darksaga

+2

फ्रैगमेंट # setRetainInstance (बूलियन) देखें और दस्तावेज़ीकरण के माध्यम से पढ़ें। यह वास्तव में वह समाधान है जिसे हम वास्तव में ढूंढ रहे हैं। जबकि गतिविधि अभी भी नष्ट हो रही है और फिर से बनाई गई है, तो टुकड़ा बरकरार रखा जा रहा है और पुन: उपयोग किया जा रहा है। इसलिए कॉलबैक DialogTestListener अभी भी सही ऑब्जेक्ट को इंगित कर रहा है और कॉन्फ़िगरेशन परिवर्तन के बाद आपको Fragments को रिवायर करने की आवश्यकता नहीं है। –

+0

इस समाधान के साथ समस्या यह है कि यदि आप "गतिविधियों को न रखें" संवाद को खोलते हैं, तो होम खोलें और होम लॉन्चर से ऐप खोलें, संवाद फिर से बनाया जाएगा और आपको एक BadParcelableException मिलेगा, मैं संघर्ष कर रहा हूं इस पर। – David

-6

एक और तरीका है कि आप गतिविधि निर्मित हो रही रोक सकता है। आपको एंड्रॉइड को बताना होगा कि आप अभिविन्यास को स्वयं बदल देंगे और एंड्रॉइड आपकी गतिविधि को फिर से नहीं बनाएगा। आप अपने मैनिफ़ेस्ट फ़ाइल को आपकी गतिविधि के लिए इस जोड़ने की जरूरत:

android:configChanges="keyboardHidden|orientation" 

यदि यह नहीं है, तो आप मानक onSaveInstanceState() अपने राज्य को बचाने और के रूप में गूगल द्वारा की सिफारिश savedInstanceState का उपयोग कर ठीक करने के लिए उपयोग कर सकते हैं।

यहाँ इसके लिए गूगल के आधिकारिक गाइड है: यदि आपने ऐसा नहीं किया http://developer.android.com/guide/components/activities.html#Lifecycle

यह अध्ययन करें। यह वास्तव में एंड्रॉइड विकास में आपकी मदद करेगा।

+0

मैं उन्मुखीकरण परिवर्तन के दौरान गतिविधि को नष्ट और पुनर्निर्मित करना बंद नहीं करना चाहता, यह इस संबंध में अपेक्षित काम करता है। मैं केवल डायलॉगफ्रैगमेंट के बीच कॉलबैक को संभालने के लिए सबसे अच्छा अभ्यास जानना चाहता हूं जिसे एक अभिविन्यास परिवर्तन के दौरान फ्रैगमेंट एक्टिविटी द्वारा खोला गया था। आपके इनपुट के लिए – darksaga

1

सबसे पहले से dialogFragment शुरू करने के लिए setTargetFragment पर कॉल करें। dialogFragment में कॉलबैक खंड और डेटा लौटने के लिए getTargetFragment का उपयोग करें। Receive result from DialogFragment

+0

हालांकि यह सही है, यह किसी प्रश्न के लिए कुछ भी नहीं करता है। चूंकि रोटेशन के बाद डेटा का स्थानांतरण और कॉलबैक बहाल करना अलग-अलग चीजें हैं। उदाहरण के लिए, कॉलबैक में मैं एक और गतिविधि खोल सकता हूं या अनुरोध कर सकता हूं। – CoolMind

2

आन्द्रे के समाधान काम करता है, एक बेहतर समाधान अपने Fragment में onAttach() दौरान अद्यतन गतिविधि प्राप्त करने के लिए है: सभी डेटा excute होगा की onactivityresultFragmentParent

इस लिंक का अनुसरण परिणाम है।

private DialogTestListener mListener; 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    mListener = (DialogTestListener) activity; 
} 
इस समाधान के साथ

, आप अब और newInstance() में Activity पारित करने के लिए की जरूरत नहीं होगी। आपको बस यह सुनिश्चित करना होगा कि Activity आपके Fragment का मालिक है DialogTestListener है। आपको राज्य को ResultReceiver समाधान में सहेजने की भी आवश्यकता नहीं है।

8

स्थैतिक तरीकों और चर का उपयोग करने के बजाय बेहतर समाधान है क्योंकि यह केवल आपके संवाद का एक उदाहरण होगा। यह गैर स्थिर सदस्य के रूप में अपने कॉलबैक स्टोर करने के लिए बेहतर है

private DialogTestListener mListener; 
public void setListener (DialogTestListener listener){ 
    mListener = listener; 
} 

तो फिर तुम इस mDialogFragment.show(getSupportFragmentManager(), DIALOG_TAG);

और जैसे टैग का उपयोग कर फिर अपने गतिविधि के onResume विधि में आप अपने श्रोता रीसेट कर सकते हैं अपने संवाद दिखाना चाहिए

protected void onResume() { 
    super.onResume(); 
    mDialogFragment = (CMFilterDialogFrg) getSupportFragmentManager().findFragmentByTag(DIALOG_TAG); 
    if(mDialogFragment != null){ 
     mDialogFragment.setListener(yourListener) 
    } 
} 
+0

धन्यवाद - यह विधि मेरे लिए काम किया! कॉलबैक के साथ संवाद Fragments का उपयोग कर मेरे लिए पहली बार। मैं थोड़ी देर के लिए इसके साथ कुश्ती कर रहा था - शुक्र है कि मैंने यह पोस्ट देखा। मैं लगभग खुद वहां था लेकिन इस पोस्ट ने समाधान +1 तक पहुंचने में मदद की! –

+0

यदि आप किसी गतिविधि से संवाद को कॉल करते हैं तो जेसन लॉन्ग सबसे अच्छा समाधान देता है, अगर आप इसे फ्रैगमेंट से कॉल करते हैं तो सबसे अच्छा समाधान देता है, और यदि आपको दोनों परिदृश्यों का सामना करना पड़ता है तो यह सबसे अच्छा समाधान है। – natario

संबंधित मुद्दे