2012-04-01 9 views
6

Ho una scheda principale TabActivity che ha due schede, A e B (per ora). Tab A carica un FragmentActivity (codice di seguito indicato) che contiene solo un FrameLayout, quindi posso caricare i miei frammenti per quella specifica scheda al suo interno.FragmentManager.popBackStack() non carica semplicemente il frammento precedente

Il primo frammento ha alcune immagini di testo e uno ListView. I dati vengono estratti da un servizio Web. Quando faccio clic su un elemento di ListView, carico i dettagli di quell'elemento in un altro frammento (anch'esso proviene da un servizio Web) e sostituisco il frammento corrente (con ListView e altri controlli) con un altro frammento di dettaglio.

Per raggiungere questo obiettivo, sto usando la libreria android-support-v4.jar per utilizzare Frammenti come erano preferiti. XML di

scheda di un FragmentActivity:

<?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:orientation="vertical" > 

     <FrameLayout 
      android:id="@+id/updates_frame" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:background="@drawable/background"/> 
    </LinearLayout> 

Tab Un FragmentActivity codice Java:

public class UpdatesFragmentActivity extends FragmentActivity implements 
    IUpdateNotifier { 

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

     //Load Initial Fragment into FrameLayout 
     //I am adding this Fragment to BackStack 
     Fragment newFragment = new UpdatesFragment(); 
     FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
     ft.addToBackStack(null); 
     ft.add(R.id.updates_frame, newFragment); 
     ft.commit(); 
    } 

    //This is an Interface method which I call with the clicked "FEED" object to load its detail in another Fragment 
    @Override 
    public void onFeedSelected(Feed feed) { 
     // Instantiate a new fragment. 
     Fragment newFragment = new FeedDetailFragment(feed); 

     // Add the fragment to the activity, pushing this transaction 
     // on to the back stack. 
     FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
     ft.replace(R.id.updates_frame, newFragment); 
     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
     ft.addToBackStack(null); 
     ft.commit(); 
    } 

    //This is another Interface Method which I call when the user presses "BACK". 
    //I am trying to load the previously loaded Fragment, which I added to BackStack. 
    //But this causes reconstruction of the previously loaded fragment. LIST in this case 
    //which call the web service. I DONT WANT TO CALL SERVICE AGAIN. 
    @Override 
    public void onBackPressed() { 
     FragmentManager fm = getSupportFragmentManager(); 
     if (fm.getBackStackEntryCount() > 0) { 
      fm.popBackStack(); 
     } 
    } 
} 

ho creato un'interfaccia IUpdateNotifier, che contiene due metodi:

public void onFeedSelected(Feed feed); 
public void onBackPressed(); 

Parent UpdatesFragmentActivity implementa questi metodi. Io chiamo questi metodi dai bambini Frammenti dopo le azioni seguenti.

  1. mi chiamano onFeedSelected (Feed feed) dal frammento che ha una ListView. Invio l'elemento del feed selezionato al parent FragmentActivity, quindi carica un altro frammento che conterrebbe i dettagli del feed.
  2. Io chiamo onBackPressed() dal secondo dettaglio del feed Frammento quando l'utente preme un pulsante che dovrebbe riportare il primo frammento che conteneva ListView con altri controlli. Come potete vedere, provo a chiamare di FragmentManager popBackStack() metodo per riportare quel primo frammento ...

Ma il primo frammento ottiene rinfrescato e carica tutti i dati dal servizio web.

In realtà non riesco ad ottenere e memorizzare i dati solo una volta, né gli aggiornamenti sono frequenti su alcuni intervalli di tempo. L'utente può aggiornare l'elenco quando lo desidera. Inizialmente, l'elenco carica i 10 elementi principali dal servizio, quindi l'utente può fare clic sul pulsante "Altro" alla fine dell'elenco se desidera caricare più articoli.

Caricherà i prossimi 10 articoli e così via. Ma penso di poter archiviare l'ArrayList recuperato in qualche variabile in UpdatesFragmentActivity e quindi semplicemente riassegnare quell'ArrayList alla scheda dell'elenco invece di caricare i dati dal servizio, ma non so come rendere Fragment a non chiamare di nuovo il servizio.

Voglio che si comporti come quando clicco sulla scheda 2 e poi di nuovo sulla scheda 1. Mostra semplicemente i dati caricati come se fossero nascosti e non chiama il servizio.

Come posso ottenere questo risultato?

+0

hai trovato una soluzione –

risposta

4

Il modello di progettazione è difettoso a causa di una scarsa separazione delle preoccupazioni. L'aggiornamento dei dati dovrebbe essere disaccoppiato dall'interfaccia utente, quindi quando un utente torna al frammento precedente non dovrebbe avere nulla a che fare con il caricamento dei dati da un servizio web.

Ci sono un paio di soluzioni semplici ma non so cosa funzionerà meglio dato che hai dato poco contesto al problema.

La prima opzione sarebbe quella di introdurre una schermata iniziale all'avvio. Questa attività farebbe uso di uno AsyncTask per scaricare i dati necessari dal servizio web. Funziona bene se vuoi che i dati vengano scaricati solo una volta durante il runtime dell'app. Assicurati di non aggiungere questa attività alla cronologia, quindi quando si preme back dall'attività successiva, l'app uscirà.

Un'altra opzione, che ho utilizzato in molte app e quella che preferisco, è l'uso di allarmi tramite lo AlarmManager. È possibile impostare aggiornamenti periodici a intervalli di tempo specifici, inoltre AlarmManager consente di raggiungere il punto in cui contiene le enumerazioni di tempo. L'allarme attiverà un broadcast receiver che eseguirà il codice personalizzato, che scaricherà i dati necessari dal servizio web e li memorizzerà.

Esiste un tutorial su questo approccio, che può essere trovato qui http://android.arnodenhond.com/tutorials/alarm-notification.

Infine; non dovresti aver bisogno di aprire il back stack per ovviare a questo problema, anche se potresti farlo per ragioni completamente diverse ma è difficile dirlo senza ulteriori informazioni.

+0

Sono davvero dispiaciuto per non aver fornito abbastanza informazioni sul problema che sto affrontando. Ho aggiornato la mia domanda ... puoi dargli un'occhiata ora ... ho cercato di spiegare il mio problema. – Aamir

+0

Non sto alterando la mia risposta in quanto non sono d'accordo sul fatto che tu abbia scelto l'approccio migliore. La risposta sopra dovrebbe guidarti nella giusta direzione. –

+0

In realtà non riesco ad ottenere e memorizzare i dati solo una volta né gli aggiornamenti sono frequenti su alcuni periodi di tempo, l'utente può aggiornare l'elenco quando vuole .. Inizialmente l'elenco carica i primi 10 elementi dal servizio, quindi l'utente può fare clic sul pulsante "Altro" alla fine della lista se vuole caricare più oggetti. caricherà i prossimi 10 articoli .. e così via. Duro apprezzo che mi abbia indirizzato ad AlarmManager che uso molto in alcuni scenari in cui sono necessari aggiornamenti periodici, ma non penso di poter usare AlarmManager in questa situazione .. Ma penso di poter archiviare l'ArrayList recuperato in alcune variabili in FragmentActivity. – Aamir

2

tua domanda non è abbastanza chiaro, fare domande più semplici e precisi ... E come dici tu sopra

popBackStack non carica l'ultimo frammento, è comunemente utilizzato per far apparire l'intero stack:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 

prima di caricare un altro frammento

beginTransaction() 
replace() Or add() 
commit() 

Questo è tutto quello che posso pensare con quella domanda

Buona fortuna

+0

La mia soluzione era fragmentManager.popBackStack (0, FragmentManager.POP_BACK_STACK_INCLUSIVE); – JWqvist

Problemi correlati