2013-10-27 10 views
13

Niedawno zaczął używać fragmentów stworzyliśmy aplikację demonstracyjną, która wygląda tak:Jak zapisać i ponownie użyć tego samego wystąpienia fragmentów?

Demo App

Kliknięcie każdego przełącza pomiędzy fragmentem 1 Fragment 2 i 3. Fragment

Co Ja próbując osiągnąć to tylko 1 przypadek każdego Fragmentu i użyć go ponownie. (Zwróć uwagę, że wszystkie fragmenty są tworzone i dodawane dynamicznie). Obecnie robię to, tworząc HashMap fragmentu i umieszczając każdą instancję i chwytając ją stamtąd.

Moje pytania brzmią: Czy jest lepszy sposób na zrobienie tego: Za pomocą metody putFragment (...) FragmentManagera? putFragment (Bundle bundle, String key, Fragment fragment) Nie mogę wymyślić, jak go użyć w moim przypadku. Jeśli ktoś może podać mi przykład użycia tej metody.

Czy zatrzymanie odniesienia do każdego fragmentu w mojej działalności jest drogie? Czy to utrzymuje wszystkie fragmenty przy życiu? Używam miękkiego odniesienia, aby poradzić sobie z tym, ale nie jestem pewien, czy jest to właściwy sposób na to. Proszę wskazać mi alternatywny sposób robienia tego lub daj mi znać, jeśli jest to najlepszy sposób, aby to osiągnąć.

Z góry dziękuję.

Oto mój kod:

UPDATE: Próbuję ponownie użyć fragmentów z tyłu stosu, starając się jedynie dodać je jeśli nie istnieje w stosie powrotem. Poniższy kod daje mi nielegalnego wyjątku państwa po I opuścisz fragmentu jeden -> wróć do niego -> następnie spróbuj nacisnąć przycisk Wstecz:

10-28 13:21:40.255: ERROR/MessageQueue-JNI(3548): java.lang.IllegalStateException: Fragment already added: FragmentOne{423db570 #0 id=0x7f050006 fragOne} 

public class MainActivity extends Activity implements View.OnClickListener { 

private Button btnOne; 
private Button btnTwo; 
private Button btnThree; 

/* Called when the activity is first created. 
    */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    initialize(); 
    if(findViewById(R.id.fl) != null){ 
     if(savedInstanceState != null) 
      return; 
    } 

    FragmentManager.enableDebugLogging(true); 
    updateView("fragOne"); 
} 

private void initialize(){ 
    btnOne = (Button) findViewById(R.id.button1); 
    btnTwo = (Button) findViewById(R.id.button2); 
    btnThree = (Button) findViewById(R.id.button3); 
    btnOne.setOnClickListener(this); 
    btnTwo.setOnClickListener(this); 
    btnThree.setOnClickListener(this); 
    fragHolder = new HashMap<String, SoftReference<Fragment>>(); 
} 

private void updateView(String tag){ 
    FragmentTransaction ft = getFragmentManager().beginTransaction(); 
    Fragment frag = getFragmentManager().findFragmentByTag(tag); 

    boolean addToStack = true; 
    if(frag == null){ 
     if(tag.equals("fragOne")) 
      frag = new FragmentOne();  
     else if(tag.equals("fragTwo")) 
      frag = new FragmentTwo(); 
     else if(tag.equals("fragThree")) 
      frag = new FragmentThree(); 
    }else{ 
     //Don't add to back stack 
     addToStack = false; 
    } 
    ft.replace(R.id.fl, frag, tag); 
    if(addToStack) 
     ft.addToBackStack(null); 
    ft.commit(); 
} 

    @Override 
    public void onClick(View v) { 
     switch(v.getId()){ 
      case R.id.button1: 
       updateView("fragOne"); 
       break; 
      case R.id.button2: 
       updateView("fragTwo"); 
       break; 
      case R.id.button3: 
       updateView("fragThree"); 
       break; 
     } 
    } 
} 
+0

Czy zapoznałeś się z FragmentTransactions? Mogą ci pomóc. –

Odpowiedz

2

wykazać FragmentTransaction następujące próbka może być pomocne ty.

Po pierwsze, chcesz zrobić wszystkie swoje rzeczy inicjujące w onCreate() swojej aktywności, które masz prawo, ale wprowadzimy kilka zmian.

public class MainActivity extends Activity implements View.OnClickListener { 

private Button btnOne; 
private Button btnTwo; 
private Button btnThree; 

/* Called when the activity is first created.*/ 
@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    initialize(); 
    if(findViewById(R.id.fl) != null) 
    { 
     if(savedInstanceState != null) 
     { 
      FragmentTransaction trans = getFragmentManager().beginTransaction(); 

      //This is where we add our first fragment 
      trans.add(R.id.fl, new FragmentOne()); 
      trans.commit(); 
     } 
    } 
} 

private void initialize() 
{ 
    btnOne = (Button) findViewById(R.id.button1); 
    btnTwo = (Button) findViewById(R.id.button2); 
    btnThree = (Button) findViewById(R.id.button3); 
    btnOne.setOnClickListener(this); 
    btnTwo.setOnClickListener(this); 
    btnThree.setOnClickListener(this); 
} 

public void onClick(View view) 
{ 
    //Here is where we'll actually transfer the fragments 

    FragmentTransaction trans = getFragmentManager().beginTransaction(); 
    switch(v.getId()){ 
     case R.id.button1: 
      trans.replace(R.id.fl, new FragmentOne()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
     case R.id.button2: 
      trans.replace(R.id.fl, new FragmentTwo()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
     case R.id.button3: 
      trans.replace(R.id.fl, new FragmentThree()); 
      trans.addToBackStack(null); 
      trans.commit(); 
      break; 
    } 
} 

Umożliwi to łatwe przejście z jednego fragmentu do drugiego.

+0

Dzięki za odpowiedź. Początkowo próbowałem tego podejścia, ale to dodaje każdą transakcję do backstack, powodując, że nadal zwiększa się dla każdej transakcji. Jak już wspomniałem, pamięć jest problemem w mojej rzeczywistej aplikacji. Dlatego chcę ograniczyć liczbę wpisów w tylnym stosie. Sądzę, że lepszym pytaniem byłoby: Jeśli możliwe jest użycie backstacku jako kolejki FIFO -> po 10 transakcjach odrzuć pierwszą, dodając 11. – Naveed

+1

Możesz wywołać 'disallowAddToBackStack()' i śledzić statyczną liczbę całkowitą lub coś, gdy masz zbyt wiele rzeczy na tylnym stosie. –

+0

Dzięki temu rozwiązaliśmy również wyjątek nielegalnego stanu, który otrzymywałem. Nadal trzeba pracować nad dodawaniem tego samego fragmentu, jeśli już go masz, ale jest to dość proste. – Naveed

1

FragmentManager wykonuje własne zarządzanie pamięcią. Zabije/odtworzy lub zachowa w pamięci twoje instancje zgodnie z jego logiką. Możesz upewnić się, że stan twojego fragmentu jest zapisany za pomocą onSaveInstanceState()

Możesz też zmusić system do utrzymania instancji przy życiu za pomocą setRetainInstance(true) w Twoim Fragmentie.

W ten sposób tworzysz transakcję.

FragmentTransaction fragmentTransaction = context.getSupportFragmentManager().beginTransaction(); 
    fragmentTransaction.replace(R.id.layout, new MyFragment(), f.getClass().getName()); 
    fragmentTransaction.commit(); 
+1

Dzięki za odpowiedź. Próbowałem już tego podejścia, jedyną różnicą, jaką zauważyłem, było to, że jeśli wpiszesz coś w fragmencie pierwszym, a następnie zamienisz go na fragment drugi, utworzenie nowej instancji fragmentu pierwszego podczas nawigacji z powrotem spowoduje, że stracisz tę zmianę jako przeznaczoną do ponownego wykorzystania to samo wystąpienie (w takim przypadku tekst nadal będzie obecny) – Naveed

Powiązane problemy