8

Ho incontrato un po 'di un posto di blocco. Ho uno scenario MOLTO simile a quello descritto a: DialogFragment - retaining listener after screen rotationCome conservare il listener nella finestra di dialogo personalizzata aperta dal frammento?

La soluzione proposta funziona bene per l'autore perché il suo dialogo viene chiamato da un'attività. Il mio caso è esattamente lo stesso, ma la mia finestra di dialogo personalizzata è chiamata da un frammento anziché da un'attività. (IE Activity-> Fragment-> Dialog)

ho implementato la stessa soluzione (impostando l'ascoltatore in onResume dal chiamante frammento), ma non funziona in questo caso.

Quello che sembra accadere è che quando lo schermo viene ruotato, Android uccide la finestra di dialogo e il frammento. Quindi li ricrea IN QUEL ORDINE. Quindi, quando il mio onCreateDialog viene chiamato sulla mia finestra di dialogo personalizzata, il frammento contenente deve ancora essere ricreato, quindi ha null per il listener da impostare per i pulsanti positivi e negativi.

Qualcuno sa un modo per aggirare questo?

Posso postare codice se qualcuno pensa che sarebbe necessario, ma è praticamente lo stesso del codice sul thread collegato.

aggiornato con CODICE:

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

Dovrai inserire il codice – Atomix

risposta

3

Ho esaminato tutte le opzioni sui collegamenti discussi e nessuna delle soluzioni ha funzionato per me. Ho anche provato un certo numero di opzioni aggiuntive dopo ulteriori googling come get/setTargetFragment e FragmentManager.put/getFragment. Questi non hanno funzionato neanche per me. Poi ho preso un altro sguardo a:

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

Dove specificamente dire "due frammenti non devono mai comunicare direttamente". Penso che questo sia uno dei casi in cui ciò è davvero dimostrato vero.

ho finito per l'attuazione del meccanismo di callback suggerito a condizione che vi e finito con questo:

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

In attività di hosting:

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

In Frammento che spara FragmentDialog:

public static final String TAG = "tag1"; 

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

Questo funziona perfettamente, se aperto, il cambio di orientamento e la modifica sono completati, in realtà attiva la funzione definitiva che ho bisogno di eseguire nel frammento chiamante invece di arrestare o non fare nulla (listener nullo).

+0

Ottimo hai trovato una soluzione! Solo un piccolo commento, questo ti rende in grado di estendere il frammento per prendere ancora un altro argomento sulla creazione, un OnEditStepDialogListener per gestire il callback, nel caso non ti piacesse gestire ogni callback nella tua classe Activity. – cYrixmorten

0

sarebbe un disastro di riferire alla vostra attività e fare che creare la finestra?

Ho appena rivisto il mio codice per vedere cosa sto facendo in quanto non ho riscontrato questo problema. Il mio prendere su di esso è qualcosa di simile:

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

Così, con questa costruzione l'attività utilizza il frammento puramente per mostrare la mappa, ma può essere utilizzato sia per i purpos di direzioni, o punti di interesse, a seconda di quale modulo è invocato.

Ora quando il modulo incontra un problema o necessita di un'interazione dell'utente, riporta a MyActivity, che ad esempio visualizza un DialogFragment.

vorrebbe dare una risposta migliore, come non vedo il motivo per cui non si dovrebbe essere in grado di invocare un DialogFragment dall'interno di un'altra Frammento e si aspettano un bel comportamento.

Nel caso in cui, hai impostato setRetainInstance (true) su di te Frammento?

Edit:

Ok, così ho appena rivisto il codice appena commesso, ecco la mia nuova idea:

estendere le argomentazioni della vostra finestra per prendere un contesto così u può chiamare in questo modo :

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

Avanti utilizzare il contesto aggiunto invece di getActivity() nella finestra di dialogo:

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

Sospetto (non sono sicuro di questo) che SherlockFragment conta come un'istanza di Attività, quindi quando si chiama getActivity() nella finestra di dialogo, è legato al proprio frammento.

+0

Non sarebbe un disastro, ma preferirei una soluzione che permetta a un frammento di rispondere a una finestra di dialogo che si innesca. Se nessun altro ha un'opzione migliore, considererò questa la migliore risposta. Ho provato setRetainInstance sul frammento, e non sembra aiutare. – user2229491

+0

appena fatto una nuova modifica (ti vengono automaticamente informati di questo?) – cYrixmorten

+0

Ho appena provato a farlo in questo modo (contesto interno e funzione setContext chiamato nel costruttore getInstance per impostarlo) e ora si blocca se si ruota dopo popup viene mostrato . Sono abbastanza sicuro che sia la stessa ragione del problema con Listener ... la finestra di dialogo viene ricreata prima del frammento così, quando esegue suCreateDialog l'oggetto contesto interno non è ancora stato impostato ... – user2229491

Problemi correlati