Bagaimana cara meneruskan variabel dari Aktivitas ke Fragmen, dan meneruskannya kembali?

140

Saya sedang membuat aplikasi android, dan saya ingin meneruskan tanggal antara aktivitas dan fragmen. Aktivitas saya memiliki tombol, yang membuka fragmen: DatePickerFragment.

Dalam aktivitas saya, saya menunjukkan tanggal, yang ingin saya ubah dengan fragmen. Jadi saya ingin meneruskan tanggal ke datepicker, dan mengirimkannya kembali ke aktivitas.

Saya sudah mencoba banyak solusi, tetapi tidak ada yang berhasil. Cara yang mudah akan memberikan argumen, tetapi ini tidak dapat dilakukan dengan fragmen.

Eugene Primako
sumber
Masalah saya sama persis dengan masalah Anda. Saya bertanya-tanya mengapa contoh hanya memperlakukan fragmen itu sendiri sebagai "pengguna" dari pemilih tanggal, bukan aktivitas yang memulainya.
Claudio

Jawaban:

216

Untuk meneruskan info ke sebuah fragmen , Anda setArguments saat membuatnya, dan Anda bisa mengambil argumen ini nanti pada metode onCreate atau onCreateView dari fragmen Anda.

Pada fungsi newInstance dari fragmen Anda, Anda menambahkan argumen yang ingin Anda kirimkan:

/**
 * 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;
}

Kemudian di dalam fragmen pada metode onCreateatau onCreateViewAnda dapat mengambil argumen seperti ini:

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

Jika sekarang Anda ingin berkomunikasi dari fragmen dengan aktivitas Anda (mengirim atau tidak data) , Anda perlu menggunakan antarmuka. Cara Anda melakukan ini dijelaskan dengan sangat baik dalam tutorial dokumentasi komunikasi antar fragmen. Karena semua fragmen berkomunikasi satu sama lain melalui aktivitas, dalam tutorial ini Anda bisa melihat bagaimana Anda bisa mengirim data dari fragmen sebenarnya ke wadah aktivitasnya untuk menggunakan data ini pada aktivitas atau mengirimnya ke fragmen lain yang berisi aktivitas Anda.

Tutorial dokumentasi:

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

jpardogo.dll
sumber
12
Saya pikir maksud orang-orang menanyakan pertanyaan ini berulang kali adalah bahwa hal itu tidak dijelaskan dengan baik dalam dokumentasi.
Michael Alan Huff
1
Saya masih bingung metode mana yang terbaik untuk digunakan, milik Anda, atau yang di bawah ini dijawab oleh @Elenasys
Yoann Hercouet
Ada cara baru untuk berbagi data antar fragmen menggunakan komponen arsitektur (I / O '17): developer.android.com/topic/libraries/architecture/…
jpardogo
Bagaimana dengan fragmen yang dibuat di dalam layout XML?
ralphgabb
Saya tidak ingin menggunakan metode statis lagi.
Ahamadullah Saikat
90

Mengirim data dari Activityke aFragment

Aktivitas:

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();

Pecahan:

Membaca nilai dalam fragmen

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

Tetapi jika Anda ingin mengirim nilai dari Fragment ke Activity, membaca jawaban jpardogo, Anda harus membutuhkan antarmuka, info selengkapnya: Berkomunikasi dengan Fragmen lain

Jorgesys
sumber
2
Bagaimana cara mengirimkan objek khusus? Saya menggunakan Parcelabletapi itu memberi sayaclass cast exception
viper
solusi ini tidak berfungsi untuk saya, tidak dapat menemukan tempat untuk mengimpor transaksi
thebeancounter
Nah, jika Anda memuat Fragmen ke dalam Aktivitas Anda, Anda dapat mengirim nilai melalui paket yang ditentukan dalam transaksi Anda. Jelaskan apa skenario Anda?
Jorgesys
9

terima kasih kepada @ ρяσѕρєя K dan Terry ... ini banyak membantu saya dan bekerja dengan sempurna

Dari Aktivitas, Anda mengirim data dengan maksud sebagai:

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

dan dalam metode 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);
}

referensi: Mengirim data dari aktivitas ke fragmen di android

mahmoud zaher
sumber
7

Gunakan perpustakaan EventBus untuk meneruskan acara yang dapat berisi variabel Anda bolak-balik. Ini adalah solusi yang bagus karena membuat aktivitas dan fragmen Anda tetap terhubung secara longgar

https://github.com/greenrobot/EventBus

SemaphoreMetaphor
sumber
4
Saya tidak bisa mengatakan ini bukan solusi yang baik, tetapi peringatan sudah ada. Meskipun EventBus sangat mudah digunakan, di sinilah letak bahayanya juga. Jika Anda mulai menambahkan terlalu banyak sinyal, sifat longgar yang digabungkan dapat membuat sangat sulit untuk melacak siapa yang menelepon siapa dan di mana berbagai peristiwa terjadi.
Johan Paul
2

Mengirim data dari Aktivitas ke Fragmen yang ditautkan oleh XML

Jika Anda membuat fragmen di Android Studio menggunakan salah satu template, misalnya File> New> Fragment> Fragment (List), maka fragmen akan ditautkan melalui XML. Metode newInstance dibuat dalam fragmen tetapi tidak pernah dipanggil sehingga tidak dapat digunakan untuk meneruskan argumen.

Sebagai gantinya, dalam Activity, ganti metode onAttachFragment

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

Kemudian baca argumen dalam metode fragmen onCreate sesuai jawaban lainnya

Lembah
sumber
2

Untuk semua developer Kotlin di luar sana:

Berikut adalah solusi yang diusulkan Android Studio untuk mengirim data ke Fragmen Anda (= saat Anda membuat Fragmen Kosong dengan File -> Baru -> Fragmen -> Fragmen (Kosong) dan Anda mencentang "sertakan metode pabrik fragmen").

Taruh ini di Fragmen Anda:

class MyFragment: Fragment {

...

    companion object {

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

.applyadalah trik yang bagus untuk menyetel data saat sebuah objek dibuat, atau seperti yang dinyatakan di sini :

Memanggil fungsi yang ditentukan [blok] dengan thisnilai sebagai penerima dan mengembalikan thisnilai.

Kemudian di Aktivitas atau Fragmen Anda lakukan:

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

dan baca Argumen di Fragmen Anda seperti:

private var isMyBoolean = false

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

Untuk "mengirim" data kembali ke Aktivitas Anda , cukup tentukan fungsi di Aktivitas Anda dan lakukan hal berikut di Fragmen Anda:

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

Nikmati keajaiban Kotlin!

Paul Spiesberger
sumber
0

Anda cukup membuat instance fragmen Anda dengan sebuah bundel:

Fragment fragment = Fragment.instantiate(this, RolesTeamsListFragment.class.getName(), bundle);
stef
sumber
-2

Deklarasi variabel publik di kelas adalah cara termudah:

Di kelas sasaran:

public class MyFragment extends Fragment {
    public MyCallerFragment caller; // Declare the caller var
...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
           Bundle savedInstanceState) {
        // Do what you want with the vars
        caller.str = "I changed your value!";
        caller.i = 9999;
        ...
        return inflater.inflate(R.layout.my_fragment, container, false);
    }
...
}

Di kelas penelepon:

public class MyCallerFragment extends Fragment {
    public Integer i; // Declared public var
    public String str; // Declared public var
        ...
            FragmentManager fragmentManager = getParentFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();

            myFragment = new MyFragment();
            myFragment.caller = this;
            transaction.replace(R.id.nav_host_fragment, myFragment)
                    .addToBackStack(null).commit();
        ...
}

Jika Anda ingin menggunakan aktivitas utama juga mudah:

Di kelas kegiatan utama:

public class MainActivity extends AppCompatActivity {
    public String str; // Declare public var
    public EditText myEditText; // You can declare public elements too.
                                // Taking care that you have it assigned
                                // correctly.
...
}

Di kelas yang dipanggil:

public class MyFragment extends Fragment {
    private MainActivity main; // Declare the activity var
...
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
           Bundle savedInstanceState) {
        // Assign the main activity var
        main = (MainActivity) getActivity();

        // Do what you want with the vars
        main.str = "I changed your value!";
        main.myEditText.setText("Wow I can modify the EditText too!");
        ...
        return inflater.inflate(R.layout.my_fragment, container, false);
    }
...
}

Catatan: Berhati-hatilah saat menggunakan peristiwa (onClick, onChanged, dll) karena Anda bisa berada dalam situasi "berkelahi" di mana lebih dari satu menetapkan variabel. Hasilnya adalah variabel terkadang tidak akan berubah atau akan kembali ke nilai terakhir secara ajaib.

Untuk lebih banyak kombinasi gunakan kreativitas Anda. :)

Andrés
sumber
1
Ini dengan erat menggabungkan aktivitas dan fragmen bersama-sama dan oleh karena itu membatasi penggunaan kembali fragmen. Kita harus mencari cara komunikasi yang tidak terlalu menyatu.
Zorayr