Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Comunicação com outros Fragments

Para reutilizar os componentes da IU de Fragment, você deve criá-los para que cada um seja completamente autossuficiente e modular e defina o próprio layout e comportamento. Assim que tiver definido esses Fragments reutilizáveis, você poderá associá-los a uma Activity e conectá-los à lógica do aplicativo para abranger a IU composta em sua totalidade.

Na maioria das vezes, você desejará que um Fragment se comunique com outro, por exemplo, para alterar o conteúdo baseado em um evento do usuário. Toda a comunicação entre Fragments é feita por meio de um ViewModel compartilhado ou de Activities associadas. Dois Fragments nunca devem comunicar-se diretamente.

A maneira recomendada de se comunicar entre Fragments é criar um objeto ViewModel compartilhado. Ambos os Fragments podem acessar o ViewModel por meio da Activity deles. Os Fragments podem atualizar dados dentro do ViewModel. Além disso, caso dados sejam expostos usando LiveData, o novo estado será enviado ao outro Fragment, desde que esteja observando o LiveData do ViewModel. Para ver como implementar esse tipo de comunicação, leia a seção “Compartilhar dados entre Fragments” no guia de ViewModel.

Se não conseguir usar um ViewModel compartilhado para se comunicar entre seus Fragments, você poderá usar interfaces para implementar manualmente um fluxo de comunicação. No entanto, talvez isso dificulte a implementação e não seja facilmente reutilizável em outros Fragments.

Definir uma interface

Para permitir que um Fragment se comunique com a Activity, você pode definir uma interface na classe do Fragment e implementá-la dentro da Activity. O Fragment captura a implementação da interface durante o método de ciclo de vida onAttach() e pode, então, chamar os métodos da interface para estabelecer comunicação com a Activity.

Este é um exemplo de comunicação de Fragment para Activity:

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

    // ...
}

MainActivity

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

Agora o Fragment pode enviar mensagens à atividade ao chamar o método onArticleSelected() (ou outros métodos na interface) usando a instância mCallback da interface OnHeadlineSelectedListener.

Por exemplo, o método a seguir no Fragment é chamado quando o usuário clica em um item de lista. O Fragment usa a interface de callback para enviar o evento à atividade relacionada.

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

Implementar a interface

Para receber callbacks de evento do Fragment, a atividade que o hospeda deve implementar a interface definida na classe do Fragment.

Por exemplo, a atividade a seguir implementa a interface do exemplo acima.

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
    }
}

Entregar uma mensagem a um Fragment

A atividade hospedeira pode enviar mensagens a um Fragment ao capturar a instância Fragment com findFragmentById(). Em seguida, a atividade chama diretamente os métodos públicos do Fragment.

Por exemplo, imagine que a atividade exibida acima possa conter outro Fragment que é usado para exibir um item especificado pelos dados retornados no método callback acima. Nesse caso, a atividade pode encaminhar a informação recebida no método callback para outro Fragment que exibirá o item:

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

Para saber mais sobre a implementação de Fragments, consulte Fragments. Ou explore o aplicativo de amostra relevante para mais informações.