Jak przekazać zmienną z Activity do Fragment i przekazać ją z powrotem?

135

Obecnie tworzę aplikację na Androida i chcę przekazać datę między działaniem a fragmentem. Moja aktywność posiada przycisk, który otwiera fragment: DatePickerFragment.

W swojej działalności pokazuję datę, którą chcę zmodyfikować fragmentem. Chcę więc przekazać datę selektorowi daty i odesłać ją do ćwiczenia.

Wypróbowałem wiele rozwiązań, ale żadne nie działa. Prostym sposobem byłoby przekazanie argumentu, ale nie można tego zrobić z fragmentami.

Eugene Primako
źródło
Mój problem jest dokładnie taki sam jak twój. Zastanawiam się, dlaczego przykłady traktują tylko same fragmenty jako „użytkowników” selektora dat, a nie aktywność, która je uruchomiła.
Claudio,

Odpowiedzi:

213

Aby przekazać informacje do fragmentu , należy ustawić Argumenty podczas jego tworzenia i można później pobrać ten argument metodą onCreate lub onCreateView swojego fragmentu.

W funkcji newInstance twojego fragmentu dodajesz argumenty, które chcesz do niego wysłać:

/**
 * Create a new instance of DetailsFragment, initialized to
 * show the text at 'index'.
 */
public static DetailsFragment newInstance(int index) {
    DetailsFragment f = new DetailsFragment();
    // Supply index input as an argument.
    Bundle args = new Bundle();
    args.putInt("index", index);
    f.setArguments(args);
    return f;
}

Następnie wewnątrz fragmentu metody onCreatelub onCreateViewmożesz pobrać argumenty w ten sposób:

Bundle args = getArguments();
int index = args.getInt("index", 0);

Jeśli chcesz teraz komunikować się ze swoim fragmentem ze swoją aktywnością (wysyłając lub nie dane) , musisz użyć interfejsów. Sposób, w jaki możesz to zrobić, jest naprawdę dobrze wyjaśniony w samouczku dokumentacji komunikacji między fragmentami. Ponieważ wszystkie fragmenty komunikują się między sobą za pośrednictwem działania, w tym samouczku możesz zobaczyć, jak możesz wysłać dane z rzeczywistego fragmentu do jego kontenera działania, aby użyć tych danych w działaniu lub wysłać je do innego fragmentu, który zawiera działanie.

Samouczek dokumentacji:

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

jpardogo
źródło
10
Myślę, że celem ludzi, którzy ciągle zadają to pytanie, jest to, że nie jest to dobrze wyjaśnione w dokumentacji.
Michael Alan Huff,
1
Nadal nie wiem, która metoda jest najlepsza w użyciu, twoja lub ta poniżej, na którą odpowiedział @Elenasys
Yoann Hercouet
Istnieje nowy sposób udostępniania danych między fragmentami przy użyciu komponentów architektury (I / O '17): developer.android.com/topic/libraries/architecture/ ...
jpardogo
A co z tymi fragmentami, które są tworzone w układzie XML?
ralphgabb
Nie chcę już używać metody statycznej.
Ahamadullah Saikat
89

Wysyłanie danych z ActivitydoFragment

Czynność:

Bundle bundle = new Bundle();
String myMessage = "Stackoverflow is cool!";
bundle.putString("message", myMessage );
FragmentClass fragInfo = new FragmentClass();
fragInfo.setArguments(bundle);
transaction.replace(R.id.fragment_single, fragInfo);
transaction.commit();

Fragment:

Odczytywanie wartości we fragmencie

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    String myValue = this.getArguments().getString("message");
    ...
    ...
    ...
}

Ale jeśli chcesz wysłać wartości z fragmentu do działania, przeczytaj odpowiedź jpardogo, potrzebujesz interfejsów, więcej informacji: Komunikacja z innymi fragmentami

Jorgesys
źródło
2
Jak przekazać obiekt niestandardowy? Użyłem, Parcelableale to dało miclass cast exception
viper
to rozwiązanie nie działa dla mnie, nie mogę znaleźć skąd zaimportować transakcję
thebeancounter
Cóż, jeśli załadujesz Fragment do swojej Aktywności, możesz wysłać wartości za pośrednictwem pakietu zdefiniowanego w Twojej transakcji. Wyjaśnij, jaki jest twój scenariusz?
Jorgesys
8

dzięki @ ρяσѕρєя K i Terry ... bardzo mi to pomaga i działa doskonale

Z Aktywności wysyłasz dane z zamiarem:

Bundle bundle = new Bundle(); 
bundle.putString("edttext", "From Activity"); 
// set Fragmentclass Arguments
Fragmentclass fragobj = new Fragmentclass();
fragobj.setArguments(bundle);

oraz w metodzie Fragment onCreateView:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    // get arguments
    String strtext = getArguments().getString("edttext");    
    return inflater.inflate(R.layout.fragment, container, false);
}

odniesienie: Wyślij dane z aktywności do fragmentu w systemie Android

mahmoud zaher
źródło
7

Użyj biblioteki EventBus, aby przekazać zdarzenie, które może zawierać zmienną, w tę iz powrotem. To dobre rozwiązanie, ponieważ pozwala na luźne powiązanie twoich działań i fragmentów

https://github.com/greenrobot/EventBus

SemaphoreMetaphor
źródło
4
Nie mogę powiedzieć, że to nie jest dobre rozwiązanie, ale słowo ostrzeżenia jest na miejscu. Chociaż EventBus jest niezwykle łatwy w użyciu, tutaj również tkwi jego niebezpieczeństwo. Jeśli zaczniesz dodawać zbyt wiele sygnałów, luźno powiązany charakter może naprawdę utrudnić śledzenie, kto dzwoni do kogo i gdzie mają miejsce różne wydarzenia.
Johan Paul,
2

Dla wszystkich programistów Kotlin:

Oto proponowane rozwiązanie Android Studio do wysyłania danych do Twojego fragmentu (= podczas tworzenia pustego fragmentu za pomocą polecenia Plik -> Nowy -> Fragment -> Fragment (pusty) i zaznaczania opcji „dołącz metody fabryki fragmentów”).

Umieść to w swoim fragmencie:

class MyFragment: Fragment {

...

    companion object {

            @JvmStatic
            fun newInstance(isMyBoolean: Boolean) = MyFragment().apply {
                arguments = Bundle().apply {
                    putBoolean("REPLACE WITH A STRING CONSTANT", isMyBoolean)
                }
            }
     }
}

.applyto fajna sztuczka do ustawiania danych podczas tworzenia obiektu, lub jak to tutaj stwierdzają :

Wywołuje określoną funkcję [blok] z thiswartością jako odbiorcą i zwraca thiswartość.

Następnie w swojej aktywności lub fragmencie wykonaj:

val fragment = MyFragment.newInstance(false)
... // transaction stuff happening here

i przeczytaj Argumenty w swoim fragmencie, takie jak:

private var isMyBoolean = false

override fun onAttach(context: Context?) {
    super.onAttach(context)
    arguments?.getBoolean("REPLACE WITH A STRING CONSTANT")?.let {
        isMyBoolean = it
    }
}

Aby „wysłać” dane z powrotem do swojego działania , po prostu zdefiniuj funkcję w swoim działaniu i wykonaj następujące czynności w swoim fragmencie:

(activity as? YourActivityClass)?.callYourFunctionLikeThis(date) // your function will not be called if your Activity is null or is a different Class

Ciesz się magią Kotlina!

Paul Spiesberger
źródło
1

Wysyłanie danych z działania do fragmentów połączonych przez XML

Jeśli utworzysz fragment w Android Studio za pomocą jednego z szablonów, np. Plik> Nowy> Fragment> Fragment (Lista), to fragment ten jest linkowany przez XML. Metoda newInstance jest tworzona we fragmencie, ale nigdy nie jest wywoływana, więc nie można jej używać do przekazywania argumentów.

Zamiast tego w Activity zastąp metodę onAttachFragment

@Override
public void onAttachFragment(Fragment fragment) {
    if (fragment instanceof DetailsFragment) {
        Bundle args = new Bundle();
        args.putInt("index", index);
        f.setArguments(args);        
     }
}

Następnie przeczytaj argumenty we fragmencie metody onCreate zgodnie z innymi odpowiedziami

Dołek
źródło
0

Możesz po prostu utworzyć instancję fragmentu za pomocą pakietu:

Fragment fragment = Fragment.instantiate(this, RolesTeamsListFragment.class.getName(), bundle);
stef
źródło