14

Activity.showDialog(DIALOG_ID);'u kullanarak,numaralı makalede anlatıldığı gibi DialogFragment sistemini kullanmak için iletişim kutularını taşıyorum. İşteDialogFragment yönlendirmede geri dönüşü değiştir

basit diyalog bazı örnek kod var:

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

geri iletişim kutusunu açtığınızda etkinlik/fragmanına bazı olay sunmak için geri aramalar kullanırken benim gelişimi sırasında ortaya çıkan bir soru var Ve işte size bazı aktivite kodları diyoruz:

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

Kod, referansı gördüğünüze göre oldukça fazla. Sorun şu ki, bir yönlendirme yaptığınızda, bir iletişim kutusu görüntülendiğinde, beklendiği gibi çalışmayı durdurur -> Etkinlik yaşam döngüsü nedeniyle, hem etkinlik hem de iletişim kutusu yeniden oluşturulur ve iletişim kutusu artık uygun değildir. yeni yeniden oluşturulmuş etkinliğe referans. Ben beklenen davranış almak ve bir oryantasyon değişikliği meydana geldiğinde iletişim yeni yeniden inşa faaliyeti geri olayları gönderir Bunu yapmak

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

:

benim activitys için onResume yöntemi aşağıdaki kodu eklendi.

Soruma ilişkin soru: Yön değiştirme sırasında bir FragmentActivity tarafından açılan DialogFragment arasındaki geri bildirimleri işlemek için 'en iyi uygulama' nedir?

Saygılarımızla

+0

Pek çok Fragment tuzağına düştüğünüze benziyor. Sizinle aynı problemi yaşadım ve bu mükemmel makaleyi okurken düzeltebildim: http://code.hootsuite.com/orientation-changes-on-android/. –

cevap

6

Evet, bu her zaman kendime düşen bir tuzak. Her şeyden önce, numaralı telefonun onResume() numaralı telefon numaranızdaki çözümünüzün bana tamamen uygun gibi geldiğini söyleyeyim.

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

Kontrol dışarı ResultReceiver doesn't survire to screen rotation için: Sonra böyle Receiver herşeyi işleyebilir

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

:

alternatif bir yolu Parcelable olarak seri hale getirilebilir bir ResultReceiver kullanmak olacaktır daha fazla detay. Yani sonunda muhtemelen Activity ile ResultReceiver yeniden sarmak gerekir.Tek fark, Activity'u DialogFragment'dan çözmenizdir.

+0

Thx! Şimdilik bazı aktivitelere ihtiyaç duyduğumda, onResume() 'çözümünü kullanacağız. <-> DialogFragment ayrıştırması ResultReceiver'a bir göz atacağım. – darksaga

+2

Parça # setRetainInstance (boolean) parçasını gözden geçirin ve belgeleri okuyun. Bu aslında aradığımız çözümdür. Etkinlik hala imha edilirken ve yeniden yaratılırken, Fragman korunmakta ve yeniden kullanılmaktadır. Bu nedenle, Geri Arama DialogTestListener hala doğru nesneyi işaret ediyor ve yapılandırma değişikliklerinden sonra Fragments'ı yeniden yazmak zorunda kalmazsınız. –

+0

Bu çözümle ilgili sorun, "Etkinlikleri saklama" özelliğini etkinleştirirseniz, iletişim kutusunu açtıktan sonra HOME tuşuna basıp, uygulamayı başlatıcıdan açın, iletişim kutusu yeniden oluşturulur ve bir BadParcelableException alırsınız. bu konuda. – David

-6

olduğu başka bir yol aktivite yeniden elde durduramaz olmasıdır. Android'e oryantasyon değişikliğini kendiniz halledeceğini ve android'in aktivitenizi yeniden oluşturmayacağını söylemelisiniz. Sen Manifest'inizde dosyasına etkinlik için bu eklemeniz gerekir:

android:configChanges="keyboardHidden|orientation" 

değil bu, o zaman senin durumunu kaydetmek ve Google tarafından önerildiği gibi savedInstanceState kullanarak kurtarmak için standart onSaveInstanceState() kullanabilirsiniz.

İşte bunun için Google'ın resmi kılavuz: Eğer henüz yapmadıysanız http://developer.android.com/guide/components/activities.html#Lifecycle

bunun üzerinden gidin. Android geliştirmede size gerçekten yardımcı olacaktır.

+0

Bir oryantasyon değişikliği sırasında imha edilen ve yeniden yaratılan aktiviteyi durdurmak istemiyorum, bu bağlamda beklendiği gibi çalışıyor. Yalnızca yönlendirme değişiklikleri sırasında bir FragmentActivity tarafından açılan DialogFragment arasındaki geri bildirimleri işlemek için en iyi uygulamayı bilmek istiyorum. Girişiniz için – darksaga

1

İlk olarak dialogFragment'u başlatmak için FragmentParent'dan setTargetFragment'u arayın. dialogFragment'da geri bildirim fragmanına ve veriye dönmek için getTargetFragment kullanın. André'nin çözüm çalışsa da Receive result from DialogFragment

+0

Bu doğru olsa da, bir soru için hiçbir şey yapmaz. Çünkü veri aktarımı ve dönüşten sonra geri çağırma geri yükleme farklı şeylerdir. Örneğin, geri aramada başka bir aktivite açabilir veya bir istekte bulunabilirim. – CoolMind

2

, daha iyi bir çözüm Fragment yılında onAttach() sırasında güncellenen aktiviteyi elde etmektir: Bütün veriler onactivityresult

FragmentParent bu bağlantıyı takip içinde excute edecek sonuçlanır.

Bu çözüm ile
private DialogTestListener mListener; 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    mListener = (DialogTestListener) activity; 
} 

, artık newInstance() yılında Activity geçmesine gerek yoktur. Sadece Fragment ürününe sahip olduğunuz Activity'un DialogTestListener olduğundan emin olmanız gerekir. Ayrıca, durumu ResultReceiver çözümünde olduğu gibi kaydetmeniz gerekmez.

8

Statik yöntemler ve değişkenler kullanmak yerine, diyaloğunuzun yalnızca bir örneğinden çalışacağından daha iyi bir çözüm var. Sonra

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

sonra etkinlik onResume yönteminde dinleyicinizin sıfırlayabilirsiniz bu mDialogFragment.show(getSupportFragmentManager(), DIALOG_TAG);

Ve benzeri TAG kullanarak iletişim göstermelidir olmayan statik üyesi olarak geri arama saklamak için iyidir

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

Teşekkürler - bu yöntem benim için çalıştı! Benim için ilk defa Dialog Fragments'ı bir geri arama ile kullanıyorum. Bir süredir bununla güreşiyordum - şükürler olsun ki bu yazıyı gördüm. Neredeyse kendimdeydim ama bu yazı bir +1 çözümüne ulaştı! –

+0

Jason Long, bir Etkinliğin iletişimini çağırırsanız en iyi çözümü verir, cuasodayleo bunu bir Fragmandan alırsanız en iyi çözümü verir ve her iki senaryo ile karşılaşmanız gerekirse bu en iyi çözümdür. – natario

İlgili konular