39

Questa domanda è principalmente per sollecitare pareri sul modo migliore per gestire la mia app. Ho tre frammenti gestiti da una sola attività. Il frammento A ha un elemento cliccabile nella foto e Frammento B ha 4 pulsanti cliccabili. L'altro frammento mostra solo i dettagli quando si fa clic sulla foto. Sto usando ActionBarSherlock.Comunicazione tra un frammento e un'attività - best practice

Screen shot

I pulsanti Avanti e Indietro bisogno di cambiare la foto per le pose successive o precedenti, rispettivamente. Potevo mantenere la foto e i pulsanti nello stesso frammento, ma volevo tenerli separati nel caso volessi riorganizzarli in un tablet.

Ho bisogno di un consiglio - dovrei combinare i frammenti A e B? In caso contrario, dovrò capire come implementare un'interfaccia per 3 elementi selezionabili.

Ho preso in considerazione l'utilizzo di Roboguice, ma lo sto già utilizzando SherlockFragmentActivity in modo da non farlo. Ho visto parlare di Otto, ma non ho visto buoni tutorial su come includere in un progetto. Quale pensi che dovrebbe essere la migliore pratica di progettazione?

Ho anche bisogno di aiuto per capire come comunicare tra un frammento e un'attività. Mi piacerebbe mantenere alcuni dati "globali" nell'applicazione, come l'ID di posa. C'è qualche codice di esempio che posso vedere oltre alle informazioni dello sviluppatore Android di questo articolo? Non è molto utile.

BTW, sto già memorizzando tutte le informazioni su ciascuna posa in un database SQLite. Questa è la parte facile.

+0

In realtà è possibile utilizzare Rogoguice con ActionBarSherlock, dare un'occhiata a https://github.com/rtyley/roboguice-sherlock. – rubenlop

+0

Otto è ancora più semplice, è impacchettato come un file .jar autonomo che puoi inserire nella cartella libs/della tua applicazione. – rubenlop

+1

@ rubenlop88 aggiungendo una libreria solo per passare alcuni dati da Fragment ad Activity? –

risposta

54

Il modo più semplice per comunicare tra attività e frammenti è l'utilizzo di interfacce. L'idea è fondamentalmente quella di definire un'interfaccia all'interno di un dato frammento A e lasciare che l'attività realizzi quell'interfaccia.

Una volta implementata quell'interfaccia, è possibile eseguire qualsiasi operazione nel metodo che sovrascrive.

L'altra parte importante dell'interfaccia è che devi chiamare il metodo astratto dal tuo frammento e ricordare di inviarlo alla tua attività. Dovrebbe prendere una ClassCastException se non eseguita correttamente.

C'è un buon tutorial su Simple Developer Blog su come fare esattamente questo genere di cose.

Spero che questo sia stato utile per voi!

+2

è quello che ho finito. Grazie. –

+1

Qualcuno sa perché l'esempio nella pagina degli sviluppatori Android riguardo l'uso di una finestra di dialogo di avviso non utilizza un'interfaccia per comunicare con l'attività? http://developer.android.com/reference/android/app/DialogFragment.html#AlertDialog – cjayem13

+1

Oppure utilizzare un EventBus https://github.com/greenrobot/EventBus – powder366

1

Non sono sicuro di aver veramente capito cosa si vuole fare, ma il modo suggerito per comunicare tra i frammenti è utilizzare i callback con l'attività, mai direttamente tra i frammenti. Vedi qui http://developer.android.com/training/basics/fragments/communicating.html

+0

Sì, in questo modo sembra confusionario, ho 2 frammenti che devono in qualche modo comunicare tra loro attraverso l'attività. C'è un tutorial migliore là fuori su come farlo? –

+1

@KristyWelsh: Mi chiedo se avete sviluppato il proprio concetto di ciò che 'Fragments' realmente sono e come funzionano, piuttosto che afferrato il concetto stesso della meta' Fragment' design. Il concetto di comunicazione con il '' Activity' utilizzando interfaces' è diverso dall'avere un '' Activity' implementano View.OnClickListener' Allora un 'Button' stampa si traduce in un elemento che viene aggiunto ad un 'ListView' (per esempio).Potresti avere un 'Activity' con FragmentA e FragmentB ma NON FragmentC - in questo caso, il concetto di avere FragmentA" sapere "come parlare direttamente con FragmentC è ridondante. – Squonk

20

Il metodo suggerito per la comunicazione tra i frammenti consiste nell'utilizzare callback \ listener gestiti dall'attività principale.

penso che il codice di questa pagina è abbastanza chiaro: http://developer.android.com/training/basics/fragments/communicating.html

Si può anche fare riferimento al Programma app IO 2012, che è stato progettato per essere un'applicazione di riferimento de facto. Si può trovare qui: http://code.google.com/p/iosched/

Inoltre, ecco una domanda SO con buone informazioni: How to pass data between fragments

0

È possibile creare dichiarare un'interfaccia pubblica con una dichiarazione di funzione nel frammento e implementare l'interfaccia nell'attività . Quindi puoi chiamare la funzione dal frammento.

0

Sto utilizzando Intenti per comunicare le azioni all'attività principale. L'attività principale è ascoltarli ignorando onNewIntent (intento intenzionale). Ad esempio, l'attività principale traduce queste azioni nei frammenti corrispondenti.

modo da poter fare qualcosa di simile:

public class MainActivity extends Activity { 

    public static final String INTENT_ACTION_SHOW_FOO = "show_foo"; 
    public static final String INTENT_ACTION_SHOW_BAR = "show_bar"; 


    @Override 
    protected void onNewIntent(Intent intent) { 
     routeIntent(intent); 
    } 

    private void routeIntent(Intent intent) { 
     String action = intent.getAction(); 
     if (action != null) {    
      switch (action) { 
      case INTENT_ACTION_SHOW_FOO: 
       // for example show the corresponding fragment 
       loadFragment(FooFragment); 
       break; 
      case INTENT_ACTION_SHOW_BAR: 
       loadFragment(BarFragment); 
       break;    
     } 
    } 
} 

Poi all'interno di qualsiasi frammento di mostrare il frammento foo:

Intent intent = new Intent(context, MainActivity.class); 
intent.setAction(INTENT_ACTION_SHOW_FOO); 
// Prevent activity to be re-instantiated if it is already running. 
// Instead, the onNewEvent() is triggered 
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); 
getContext().startActivity(intent); 
2

ci sono severals modi per comunicare tra le attività, i frammenti, servizi, ecc L'ovvio è comunicare usando le interfacce. Tuttavia, non è un modo produttivo per comunicare. Devi implementare gli ascoltatori ecc.

Il mio suggerimento è di utilizzare un bus eventi. Il bus eventi è un'implementazione del modello di pubblicazione/sottoscrizione.

è possibile iscriversi agli eventi nella vostra attività e quindi si può inserire che gli eventi nella tua frammenti ecc

Qui on my blog post potete trovare maggiori dettagli su questo modello e anche an example project per mostrare l'utilizzo.

5

E 'implementato da call back Interfaccia: Prima di tutto dobbiamo fare un'interfaccia:

public interface UpdateFrag { 
    public void updatefrag(); 
    } 

Nell'attività fare il seguente codice:

UpdateFrag updatfrag ; 
public void updateApi(UpdateFrag listener) { 
     updatfrag = listener; 
    } 

dall'evento, da dove il callback deve sparare in attività:

updatfrag.updatefrag(); 

In Frammento implementare i nterface nel CreateView fare il seguente codice:

((Home)getActivity()).updateApi(new UpdateFrag() { 
       @Override 
       public void updatefrag() { 
        .....your stuff...... 
       } 
      }); 
1

Ho fatto una libreria di annotazione che può fare il cast per voi. controllalo. https://github.com/zeroarst/callbackfragment/

@CallbackFragment 
public class MyFragment extends Fragment { 

    @Callback 
    interface FragmentCallback { 
     void onClickButton(MyFragment fragment); 
    }  
    private FragmentCallback mCallback; 

    @Override 
    public void onClick(View v) { 
     switch (v.getId()) { 
      case R.id.bt1 
       mCallback.onClickButton(this); 
       break; 
      case R.id.bt2 
       // Because we give mandatory = false so this might be null if not implemented by the host. 
       if (mCallbackNotForce != null) 
       mCallbackNotForce.onClickButton(this); 
       break; 
     } 
    } 
} 

Si genera quindi una sottoclasse di vostro frammento. E aggiungilo a FragmentManager.

public class MainActivity extends AppCompatActivity implements MyFragment.FragmentCallback { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     getSupportFragmentManager().beginTransaction() 
      .add(R.id.lo_fragm_container, MyFragmentCallbackable.create(), "MY_FRAGM") 
      .commit(); 
    } 

    Toast mToast; 

    @Override 
    public void onClickButton(MyFragment fragment) { 
     if (mToast != null) 
      mToast.cancel(); 
     mToast = Toast.makeText(this, "Callback from " + fragment.getTag(), Toast.LENGTH_SHORT); 
     mToast.show(); 
    } 
}