Berkomunikasi dengan fragmen lain

Untuk menggunakan kembali komponen UI Fragmen, Anda harus membuatnya sebagai komponen yang sepenuhnya berfungsi sendiri dan modular yang menentukan tata letak dan perilakunya sendiri. Setelah menentukan Fragmen yang dapat digunakan kembali ini, Anda dapat mengaitkannya dengan Aktivitas dan menghubungkannya dengan logika aplikasi untuk mewujudkan keseluruhan UI gabungan.

Anda akan sering menginginkan satu Fragmen untuk berkomunikasi dengan yang lainnya, misalnya untuk mengubah konten berdasarkan peristiwa pengguna. Semua komunikasi Fragmen ke Fragmen dilakukan baik melalui ViewModel bersama atau melalui Aktivitas terkait. Dua Fragmen tidak boleh berkomunikasi secara langsung.

Cara yang direkomendasikan untuk berkomunikasi antar fragmen adalah dengan membuat objek ViewModel bersama. Kedua fragmen dapat mengakses ViewModel melalui Aktivitas pemuat. Fragmen dapat memperbarui data dalam ViewModel dan jika data diekspos menggunakan LiveData, status baru akan dikirim ke fragmen lainnya selama Fragmen tersebut mengamati LiveData dari ViewModel. Untuk mengetahui cara mengimplementasikan komunikasi semacam ini, baca bagian 'Berbagi data antar-Fragmen' di panduan ViewModel.

Jika Anda tidak dapat menggunakan ViewModel bersama untuk berkomunikasi antar-Fragmen, Anda dapat menerapkan alur komunikasi secara manual menggunakan antarmuka. Namun hal ini pada akhirnya membuat lebih banyak pekerjaan untuk diterapkan dan tidak mudah digunakan kembali di Fragmen lain.

Menentukan Antarmuka

Untuk mengizinkan Fragmen berkomunikasi sampai dengan Aktivitasnya, Anda dapat menentukan antarmuka dalam class Fragmen dan mengimplementasikannya pada Aktivitas. Fragmen memperoleh implementasi antarmuka selama metode siklus proses onAttach() dan kemudian dapat memanggil metode Antarmuka untuk berkomunikasi dengan Aktivitas.

Berikut ini contoh komunikasi Fragmen ke Aktivitas:

HeadlinesFragment

Kotlin

    class HeadlinesFragment : ListFragment() {
        internal var callback: OnHeadlineSelectedListener

        fun setOnHeadlineSelectedListener(callback: OnHeadlineSelectedListener) {
            this.callback = callback
        }

        // This interface can be implemented by the Activity, parent Fragment,
        // or a separate test implementation.
        interface OnHeadlineSelectedListener {
            fun onArticleSelected(position: Int)
        }

        // ...
    }
    

Java

    public class HeadlinesFragment extends ListFragment {
        OnHeadlineSelectedListener callback;

        public void setOnHeadlineSelectedListener(OnHeadlineSelectedListener callback) {
            this.callback = callback;
        }

        // This interface can be implemented by the Activity, parent Fragment,
        // or a separate test implementation.
        public interface OnHeadlineSelectedListener {
            public void onArticleSelected(int position);
        }

        // ...
    }
    

AktivitasUtama

Kotlin

    class MainActivity : Activity(), HeadlinesFragment.OnHeadlineSelectedListener {
        // ...

        fun onAttachFragment(fragment: Fragment) {
            if (fragment is HeadlinesFragment) {
                fragment.setOnHeadlineSelectedListener(this)
            }
        }
    }
    

Java

    public static class MainActivity extends Activity
            implements HeadlinesFragment.OnHeadlineSelectedListener{
        // ...

        @Override
        public void onAttachFragment(Fragment fragment) {
            if (fragment instanceof HeadlinesFragment) {
                HeadlinesFragment headlinesFragment = (HeadlinesFragment) fragment;
                headlinesFragment.setOnHeadlineSelectedListener(this);
            }
        }
    }
    

Sekarang fragmen dapat mengirimkan pesan ke aktivitas dengan memanggil metode onArticleSelected() (atau metode lain dalam antarmuka) menggunakan instance mCallback dari antarmuka OnHeadlineSelectedListener.

Misalnya, metode berikut dalam fragmen dipanggil saat pengguna mengklik item daftar. Fragmen tersebut menggunakan antarmuka callback untuk mengirimkan peristiwa ke aktivitas induk.

Kotlin

    override fun onListItemClick(l: ListView, v: View, position: Int, id: Long) {
        // Send the event to the host activity
        callback.onArticleSelected(position)
    }
    

Java

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Send the event to the host activity
        callback.onArticleSelected(position);
    }
    

Mengimplementasikan Antarmuka

Untuk menerima callback peristiwa dari fragmen, aktivitas yang menghostingnya harus mengimplementasikan antarmuka yang ditentukan dalam class fragmen.

Misalnya, aktivitas berikut mengimplementasikan antarmuka dari contoh di atas.

Kotlin

    class MainActivity : Activity(), HeadlinesFragment.OnHeadlineSelectedListener {
        ...

        fun onArticleSelected(position: Int) {
            // The user selected the headline of an article from the HeadlinesFragment
            // Do something here to display that article
        }
    }
    

Java

    public static class MainActivity extends Activity
            implements HeadlinesFragment.OnHeadlineSelectedListener{
        ...

        public void onArticleSelected(int position) {
            // The user selected the headline of an article from the HeadlinesFragment
            // Do something here to display that article
        }
    }
    

Mengirim Pesan ke Fragmen

Aktivitas host dapat mengirimkan pesan ke fragmen dengan mengambil instance Fragment dengan findFragmentById(), kemudian langsung memanggil metode publik fragmen tersebut.

Misalnya, andaikan bahwa aktivitas yang ditunjukkan di atas dapat berisi fragmen lain yang digunakan untuk menampilkan item yang ditentukan oleh data yang ditampilkan dalam metode callback tersebut. Dalam hal ini, aktivitas dapat meneruskan informasi yang diterima dalam metode callback ke fragmen lain yang akan menampilkan item tersebut:

Kotlin

    class MainActivity : Activity(), HeadlinesFragment.OnHeadlineSelectedListener {
        ...

        fun onArticleSelected(position: Int) {
            // The user selected the headline of an article from the HeadlinesFragment
            // Do something here to display that article

            val articleFrag = supportFragmentManager.findFragmentById(R.id.article_fragment) as ArticleFragment?

            if (articleFrag != null) {
                // If article frag is available, we're in two-pane layout...

                // Call a method in the ArticleFragment to update its content
                articleFrag.updateArticleView(position)
            } else {
                // Otherwise, we're in the one-pane layout and must swap frags...
                // Create fragment and give it an argument for the selected article
                val newFragment = ArticleFragment()
                val args = Bundle()
                args.putInt(ArticleFragment.ARG_POSITION, position)
                newFragment.arguments = args

                val transaction = supportFragmentManager.beginTransaction()

                // Replace whatever is in the fragment_container view with this fragment,
                // and add the transaction to the back stack so the user can navigate back
                transaction.replace(R.id.fragment_container, newFragment)
                transaction.addToBackStack(null)

                // Commit the transaction
                transaction.commit()
            }
        }
    }
    

Java

    public static class MainActivity extends Activity
            implements HeadlinesFragment.OnHeadlineSelectedListener{
        ...

        public void onArticleSelected(int position) {
            // The user selected the headline of an article from the HeadlinesFragment
            // Do something here to display that article

            ArticleFragment articleFrag = (ArticleFragment)
                    getSupportFragmentManager().findFragmentById(R.id.article_fragment);

            if (articleFrag != null) {
                // If article frag is available, we're in two-pane layout...

                // Call a method in the ArticleFragment to update its content
                articleFrag.updateArticleView(position);
            } else {
                // Otherwise, we're in the one-pane layout and must swap frags...

                // Create fragment and give it an argument for the selected article
                ArticleFragment newFragment = new ArticleFragment();
                Bundle args = new Bundle();
                args.putInt(ArticleFragment.ARG_POSITION, position);
                newFragment.setArguments(args);

                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

                // Replace whatever is in the fragment_container view with this fragment,
                // and add the transaction to the back stack so the user can navigate back
                transaction.replace(R.id.fragment_container, newFragment);
                transaction.addToBackStack(null);

                // Commit the transaction
                transaction.commit();
            }
        }
    }
    

Untuk mempelajari implementasi Fragmen lebih lanjut, lihat Fragmen. Anda juga dapat mempelajari lebih lanjut dengan menjelajahi aplikasi contoh yang relevan.