2013-07-03 24 views
9

Mam numer Activity z wieloma numerami Fragment. Chcę pokazać DialogFragment lub otworzyć kolejny Fragment z jednego z Fragment. Wiem, że to Activity powinno być tym, któremu zlecono otwieranie Fragment s, więc zamiast tego próbowałem kilku rzeczy.Aktywność i interakcja fragmentów

PIERWSZA
Próbowałem użyć getActivity() i oddać go więc mogę wywołać metodę w Activity pokazać Fragment jednak stwarza to zależność w Fragment z Activity i chciałbym, aby uniknąć dodawania zależnością Jeśli to możliwe.

DRUGI
Następny Próbowałem słuchacza powiadomić Activity że powinien pokazać się Fragment. Stworzyłem więc klasę w Activity, aby zaimplementować interfejs odbiornika. Ale miałem problemy, ponieważ musiałem użyć New MyActivity().new Listener(); i gdybym spróbował użyć getSupportFragmentManager(), rzuciłbym getSupportFragmentManager(), ponieważ to wystąpienie Activity nie zostało zainicjalizowane.

TRZECI
Potem próbował mieć Activity zaimplementować słuchacza bezpośrednio która działa, bo wtedy mam tylko tworząc zależność ze słuchaczem, a nie aktywny. Jednak teraz dochodzę do punktu, w którym mój Activity będzie implementował 2 - 4 różne interfejsy, co powoduje, że jestem niezdecydowany, ponieważ znacznie zmniejszy to spójność.

Tak więc, jakikolwiek sposób próbowałem, wydaje mi się, że wpadam na ceglany mur i tworzę zależności, ale nie jestem pewien, czy muszę to stwarzać. Czy wkręca się i muszę iść z jedną z tych opcji? Jeśli tak, która opcja byłaby najlepsza? Każda pomoc lub sugestie są bardzo mile widziane.

+0

Jest wiele sposobów na zrobienie tego, wolę rzeczy odseparowane, jak to możliwe, a do tego podoba mi się autobus. Zobacz otto, na przykład: http://square.github.io/otto/. (Pozwala pozbyć się całego interfejsu/listwy słuchacza. Przekazywać dane, robić to z silnymi typami, robić to w jasny, zwięzły sposób.) –

+0

Wydaje się obiecujące. Muszę to sprawdzić. Dzięki za wskazówkę. –

Odpowiedz

10

Osobiście chciałbym powiedzieć, że fragmenty powinny być uważane za elementy wielokrotnego użytku i modułowe. Aby zapewnić tę ponowną użyteczność, fragmenty nie powinny wiele wiedzieć o swoich działaniach nadrzędnych. Ale w zamian działania muszą wiedzieć o posiadanych fragmentach.

Tak więc pierwsza opcja nie powinna być nigdy brana pod uwagę w mojej opinii z powodu zależności, o której wspomniałeś, powodując bardzo silnie powiązany kod.

O drugiej opcji fragmenty mogą delegować dowolne decyzje dotyczące aplikacji lub decyzji związanych z interfejsem użytkownika (pokazując nowy fragment, podejmując decyzję, co zrobić, gdy wystąpi zdarzenie specyficzne dla fragmentu itp.) Do swoich działań nadrzędnych. Zatem twoi słuchacze/wywołania zwrotne powinny być specyficzne dla fragmentów, a zatem powinny być zadeklarowane we fragmentach. A działania utrzymujące te fragmenty powinny implementować te interfejsy i decydować, co robić.

Dla mnie trzecia opcja ma więcej sensu. Uważam, że działania są bardziej czytelne pod względem tego, co trzymają i robią w przypadku konkretnych zwrotów. Ale tak, masz rację, twoja działalność może stać się obiektem boga.

Może chcesz sprawdzić projekt Square Otto, jeśli nie chcesz zaimplementować kilku interfejsów. To w zasadzie autobus zdarzeń.

+0

Dziękuję Tobie i @ Colharsie za wskazanie mi biblioteki Otto. Wydaje się to bardzo obiecujące i wydaje się, że osiągnie to, czego szukam. Dziękuję wszystkim za pomoc. –

3

Myślę, że twoja druga opcja jest na dobrej drodze.

W swojej fragmentu zdefiniować interfejs słuchacza:

class MyFragment ... 
{ 
    public interface IMyFragmentListenerInterface 
    { 
     void DoSomething(); 
    } 
} 

Czy aktywność implementować interfejs:

class MyActivity 
{ 
    class MyListener1 implements IMyFragmentListenerInterface { ... } 
} 

Przepuścić słuchacza do fragmentu. Lubię to robić w konstruktorze Fragmentu, ale działa to tylko wtedy, gdy samodzielnie zarządzasz swoimi fragmentami. Zamiast tego możesz dodać do swojego fragmentu metodę setListener.

+3

Istnieje problem z podejściem 'setListener': jeśli Fragment zostanie zniszczony i ponownie utworzony przez system operacyjny (przy użyciu domyślnego pustego konstruktora), odniesienie do słuchacza zostanie utracone. Najlepszym sposobem na osiągnięcie tego jest umieszczenie kodu w metodzie 'onAttach' w celu przypisania aktywności macierzystej fragmentu do roli słuchacza, sprawdzając w środowisku wykonawczym, czy obsługuje on wymagany interfejs. Zobacz http://developer.android.com/guide/components/fragments.html: "Tworzenie wywołań zwrotnych zdarzeń w działaniu". –

0

Próbowałeś coś takiego (z fragmentu):

FragmentTransaction ft = 
    getActivity().getSupportFragmentManager().beginTransaction(); 
Fragment prev = 
    getActivity().getSupportFragmentManager().findFragmentByTag("some_name"); 
if (prev != null) { 
    ft.remove(prev); 
} 
ft.addToBackStack(null); 

DialogFragment dialogFragment = DialogFragmentClass.newInstance(); 
dialogFragment.show(ft, "some_name"); 

daj mi znać, wiwaty.

2

Będziesz musiał przekazać swoje dane z Fragmentu X do swojego FragmentActivity, który przekaże te dane do Twojego Fragmentu Y. Robisz to za pośrednictwem interfejsu zdefiniowanego w klasie fragmentów i tworzysz wywołanie, które jest zdefiniowane w onAttach().

Więcej informacji na temat jak to zrobić tutaj Communication With other Fragments

Krótki przykład rozważmy Fragment A i B. Fragment Fragment A to lista fragment i gdy element jest zaznaczony to się zmieni, co jest wyświetlane w Fragment B. Proste, prawda?

Najpierw należy zdefiniować fragment A jako taki.

public class FragmentA extends ListFragment{ 

    //onCreateView blah blah blah 

} 

A oto fragment B

public class FragmentB extends Fragment{ 

//onCreateView blah blah blah 

} 

A oto moja FragmentActivity, które nimi rządzą zarówno

public class MainActivity extends FragmentActivity{ 

//onCreate 
//set up your fragments 

} 

Przypuszczalnie masz coś takiego już teraz oto jak byś zmienił Fragmenta (fragment listy, z którego musimy pobrać dane).

public class FragmentA extends ListFragment implements onListItemSelectedListener, onItemClickListener{ 

OnListItemSelectedListener mListener; 

    //onCreateView blah blah blah 



// Container Activity must implement this interface 
    public interface OnListItemSelectedListener { 
    public void onListItemSelected(int position); 
} 


} 


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

    // This makes sure that the container activity has implemented 
    // the callback interface. If not, it throws an exception 
    try { 
     mListener = (OnListItemSelectedListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() 
       + " must implement OnListItemSelectedListener"); 
    } 
} 


    @Override 
public void onItemClick(AdapterView<?> parent, View view, int position, long id){ 


//Here's where you would get the position of the item selected in the list, and pass that position(and whatever other data you need to) up to the activity 
//by way of the interface you defined in onAttach 

    mListener.onListItemSelected(position); 


} 

Najważniejszą kwestią jest tutaj, że Twoja nadrzędna aktywność implementuje ten interfejs, inaczej otrzymasz wyjątek. Jeśli zostanie to pomyślnie zaimplementowane, za każdym razem, gdy wybrany zostanie element z fragmentu listy, Twoja aktywność zostanie powiadomiona o jego pozycji. Oczywiście można zmienić interfejs z dowolną liczbą lub typem parametrów, w tym przykładzie właśnie podajemy naszą całkowitą pozycję. Mam nadzieję, że to trochę wyjaśnia, człowieku, powodzenia.

0

Aby uzyskać maksimum w luźnym sprzęgu, możesz skorzystać z autobusu takiego jak OTTO z Square lub EventBus z GreenRobot. Twoje fragmenty mogą wywoływać zdarzenia, które są obsługiwane przez Twoją aktywność i na odwrót. Najfajniejsze jest to, że komponenty (działania, fragmenty) nie mają ze sobą nic wspólnego i nie trzeba zadeklarować żadnych interfejsów ani wywołań zwrotnych.

Używam go we wszystkich moich projektach, jest wytrzymały i ma mały lub żaden wpływ na wydajność (w normalnych warunkach).

2

Tworzenie interfejsu

public interface ListenFromActivity { 
    void doSomethingInFragment(); 
} 

W Klasa aktywności zachować refrence z ListenFromActivity interfejsu

public ListenFromActivity activityListener; 

Dodać metodę publiczną, aby ustawić słuchacz

public void setActivityListener(ListenFromActivity activityListener) { 
     this.activityListener = activityListener; 
    } 

Dodaj jakiś punkt wyzwalania w klasie działalności , h ere Użyłem interakcji użytkownika

@Override 
    public void onUserInteraction() { 
     super.onUserInteraction(); 

     if (null != activityListener) { 
      activityListener.doSomethingInFragment(); 
     } 
    } 

Teraz w klasie Fragment

dokonać fragment wdrożyć klasa w interfejs

public class SomeFragment extends Fragment implements ListenFromActivity 

Android studio poprosi wdrożyć metodę interfejsu w fragmencie

void doSomethingInFragment() 
{//Add your code here 
} 

części końcowej części przykład detektor aktywności, jak to w sposób fragment onCreate

((ListnerActivity) getActivity()).setActivityListener(SomeFragment.this); 

WYKONANE !!. teraz możesz wywołać metodę fragmentu z działania.

Powiązane problemy