8

Natknąłem się na blokadę drogi. Mam scenariusz BARDZO podobny do tego opisanego pod adresem: DialogFragment - retaining listener after screen rotationJak zachować słuchacza w niestandardowym oknie dialogowym otwieranym z fragmentu?

Proponowane rozwiązanie działa dobrze dla autora, ponieważ jego dialog jest wywoływany z działania. Moja sprawa jest dokładnie taka sama, ale moje Niestandardowe okno dialogowe jest wywoływane z fragmentu zamiast z działania. (IE Activity-> Fragment-> Dialog)

Zaimplementowałem to samo rozwiązanie (ustawienie detektora w onResume z fragmentu wywołującego), ale nie działa w tym przypadku.

Wygląda na to, że po obróceniu ekranu Android zabija Dialog i Fragment. Następnie odtwarza je W TYM ZAMÓWIENIU. Tak więc, gdy mój onCreateDialog jest wywoływany w moim niestandardowym oknie dialogowym, zawierający go Fragment nie został jeszcze odtworzony, więc ma wartość NULL dla odbiornika, aby ustawić dla pozytywnych i negatywnych przycisków.

Czy ktoś wie, jak to obejść?

Mogę opublikować kod, jeśli ktoś myśli, że będzie to konieczne, ale jest prawie taki sam jak kod w połączonym wątku.

aktualizowana o kodzie:

public class RecipeDetailEditFragment extends SherlockFragment implements DialogInterface.OnClickListener { 
    private EditStepFragmentDialog stepDialog; 
    private Recipe newRecipe; //main data object implements parcelable 
    ... 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     ... 
     stepDialog = EditStepFragmentDialog.newInstance(newRecipe); 
     //I've also tried passing 'this' into the newInstance constructor and 
     //setting the listener there, but that doesn't work either 
    } 

    public void onResume() { 
     stepDialog.setListener(this); 
     super.onResume(); 
    } 
    ... 
} 


public class EditStepFragmentDialog extends DialogFragment { 
    private DialogInterface.OnClickListener ocl; 
    private static final String ARG_RECIPE = "recipe"; 
    private Recipe recipe; 

    public EditStepFragmentDialog() {} 

    public static EditStepFragmentDialog newInstance(Recipe rec) { //(Recipe rec, DialogInterface.OnClickListener oc) as mentioned doesn't work. 
     EditStepFragmentDialog dia = new EditStepFragmentDialog(); 
     Bundle args = new Bundle(); 
     args.putParcelable(ARG_RECIPE, rec); 

     //dia.setListener(oc); 
     return dia; 
    } 

    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     AlertDialog.Builder adb = new AlertDialog.Builder(getActivity()); 

     if (getArguments().containsKey(ARG_RECIPE)) { 
      recipe = (Recipe) getArguments().getParcelable(ARG_RECIPE); 
     } 
     ... 

     adb.setPositiveButton("Done", ocl); 
     adb.setNegativeButton("Cancel", ocl); 

     ... 

     return adb.create(); 
    } 

    public void setListener(DialogInterface.OnClickListener cl) { 
     ocl = cl; 
    } 
} 
+0

Będziesz musiał opublikować kod – Atomix

Odpowiedz

3

Przebiegłem wszystkie opcje omawianych linków i żadne z rozwiązań nie działało dla mnie. Wypróbowałem także wiele dodatkowych opcji po dalszym uruchomieniu google, takich jak get/setTargetFragment i FragmentManager.put/getFragment. Te też nie działały dla mnie. Potem wziął kolejny spojrzeć na:

http://developer.android.com/training/basics/fragments/communicating.html

Gdzie oni konkretnie powiedzieć „dwa fragmenty nigdy nie powinni komunikować się bezpośrednio”. Uważam, że jest to jeden z przypadków, w których to się naprawdę sprawdziło.

skończyło się na wdrażaniu sugerowany mechanizm callback umieszczono tam i skończyło się tak:

W DialogFragment:

public interface OnEditStepDialogListener { 
    public void onEditStepDialogPositive(int pos, String description); 
} 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 

    try { 
     mCallback = (OnEditStepDialogListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() + " must implement OnEditStepDialogListener"); 
    } 
} 

Hosting działalność:

public class MyActivity extends SherlockFragmentActivity implements EditStepFragmentDialog.OnEditStepDialogListener { 

... 

@Override 
public void onEditStepDialogPositive(int pos, String desc) { 
    FragmentManager fm = getSupportFragmentManager(); 
    RecipeDetailEditFragment ef = (RecipeDetailEditFragment)fm.findFragmentByTag(RecipeDetailEditFragment.TAG); 

    ef.applyStepEdit(pos, desc); 
} 

W fragment, który odpala FragmentDialog:

public static final String TAG = "tag1"; 

public void applyStepEdit(int pos, String description) { 
    ... 
} 

Działa to idealnie, jeśli jest otwarte, a zmiana orientacji i edycja jest zakończona, to faktycznie uruchamia ostateczną funkcję, którą muszę uruchomić w Fragmentu wywołującym, zamiast awarii lub braku działania (zerowy słuchacz).

+0

Dobrze, że znalazłeś rozwiązanie! Tylko mały komentarz, dzięki czemu możesz rozszerzyć fragment, aby wziąć jeszcze jeden argument na temat tworzenia, OnEditStepDialogListener do obsługi wywołania zwrotnego, na wypadek gdybyś nie lubił obsługiwać każdego wywołania zwrotnego w twojej klasie aktywności. – cYrixmorten

0

byłaby to katastrofa zgłosić powrót do aktywności i sprawiają, że tworzenie okna?

Właśnie przejrzałem mój kod, aby zobaczyć, co robię, ponieważ nie napotkałem tego problemu. My się na nim jest coś takiego:

- MyActivity 
    | 
    ---- MapsFragmet (for example) 
    | 
    ---- DirectionsModule (simple class that is handed Context) 
    | 
    ---- PointsOfInterestModule (simple class that is handed Context) 

Zatem z tej konstrukcji aktywność wykorzystuje fragment czysto pokazać mapę, ale można go używać zarówno dla przeznac kierunków czy punktów zainteresowania, w zależności od modułu jest wywoływana.

Teraz, gdy moduł napotyka problem lub potrzebuje reakcji użytkownika, zgłasza się z powrotem do MyActivity, który następnie wyświetla na przykład DialogFragment.

Chciałbym dać lepszą odpowiedź, ponieważ nie rozumiem, dlaczego nie powinieneś móc wywoływać DialogFragment z innego Fragmentu i oczekiwać miłego zachowania.

Czy na wszelki wypadek ustawiłeś setRetainInstance (true) na swoim fragmencie?

Edit:

Ok, więc po prostu sprawdził Twój nowo popełnione kodu, tu jest mój nowy pomysł:

Extend argumenty swoim oknie wziąć kontekst więc u można nazwać tak :

stepDialog = EditStepFragmentDialog.newInstance(getActivity(), newRecipe); 

Następny wykorzystać dodatkowy kontekst zamiast getActivity() w Dialog:

AlertDialog.Builder adb = new AlertDialog.Builder(context); 

Podejrzewam (nie jestem pewien), że SherlockFragment liczy się jako instancja działania, więc kiedy wywołasz funkcję getActivity() w twoim oknie dialogowym, jest ona powiązana z twoim fragmentem.

+0

To nie będzie katastrofa, ale wolę rozwiązanie, które pozwala Fragmentowi odpowiedzieć na dialog, który wyzwala. Jeśli nikt inny nie ma lepszej opcji, uznaję to za najlepszą odpowiedź. Próbowałem setRetainInstance na fragmencie i wydawało się to nie pomagać. – user2229491

+0

właśnie utworzyłem nową edycję (otrzymujesz automatycznie o tym informację?) – cYrixmorten

+0

Po prostu próbowałem zrobić to w ten sposób (wewnętrzny kontekst i funkcja setContext wywoływana w konstruktorze getInstance) i teraz zawiesza się, gdy obrócisz się po wyświetleniu wyskakującego okienka . Jestem prawie pewien, że jest to ten sam powód, co problem z Listener ... Dialog jest odtwarzany przed Fragmentem, więc gdy po raz pierwszy uruchomi się na CreateDialog wewnętrzny obiekt kontekstu nie został jeszcze ustawiony ... – user2229491

Powiązane problemy