Связь с другими фрагментами

Этот урок научит вас

  1. Определение интерфейса
  2. Реализация интерфейса
  3. Доставка сообщения во фрагмент

Вы также должны прочитать

Попробуйте

Скачать образец

FragmentBasics.zip

Чтобы повторно использовать фрагменты, вы должны создавать каждый из них как полностью автономный модульный компонент, который определяет свой собственный макет и поведение. Как только вы определили эти фрагменты многократного использования, можно связать их с деятельностью и соединить их с логикой приложения, чтобы осуществить полную компоновку пользовательского интерфейса.

Чаще всего вы хотите связать фрагменты между собой, например, чтобы изменить содержание, основанное на событиях пользователя. Вся связь между фрагментами выполняется через соответствующую деятельность. Два фрагменты никогда не должны общаться напрямую.

Определение интерфейса

Чтобы разрешить фрагменту общаться с его деятельностью, можно определить интерфейс в классе фрагмента и реализовать его в деятельности. Фрагмент захватывает реализацию интерфейса во время его метода жизненного цикла onAttach(), а затем может вызывать методы интерфейса, чтобы общаться с деятельностью.

Вот пример общения между фрагментом и деятельностью:

public class HeadlinesFragment extends ListFragment {
    OnHeadlineSelectedListener mCallback;

    // Container Activity must implement this interface
    public interface OnHeadlineSelectedListener {
        public void onArticleSelected(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 {
            mCallback = (OnHeadlineSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnHeadlineSelectedListener");
        }
    }
    
    ...
}

Теперь фрагмент может доставлять сообщения в деятельность вызывая onArticleSelected() метод (или другие методы интерфейса), используя mCallback экземпляр OnHeadlineSelectedListener интерфейса.

Например, следующий метод фрагмента вызывается, когда пользователь нажимает на элемент списка. Фрагмент использует интерфейс обратного вызова для доставки событий в родительскую деятельность.

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

Реализация интерфейса

Для получения обратных вызовов из фрагмента, деятельность в которой фрагмент размещен должна реализовать интерфейс, определенный в классе фрагмента.

Например, следующая деятельность реализует интерфейс из приведенного выше примера.

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

Доставка сообщения во фрагмент

Деятельность, содержащая фрагмент, может доставлять сообщения во фрагменты, захватив Fragment экземпляр с помощью findFragmentById(), затем напрямую вызывать общедоступные методы фрагмента.

Например, представьте, что деятельность показанная выше может содержать другой фрагмент, который используется для отображения элемента, указанного в данных возвращаемых методом обратного вызова выше. В этом случае деятельность может передать информацию, полученную в методе обратного вызова, в другой фрагмент, который будет отображать элемент:

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