1. ホーム
  2. アンドロイド

OnFragmentInteractionListener/ Fragment to Activity, Fragment to Fragment メッセージングを実装する必要があります。

2022-02-22 21:15:15
<パス

この問題の原因は、Fragment に関連する Activity が OnFragmentInteractionListener インターフェースを実装していないためです。
では、なぜ、どのようにこのインターフェースを実装する必要があるのでしょうか?順を追って見ていきましょう...。

フラグメントとアクティビティ、フラグメントとフラグメントの間の情報の受け渡し

2つのFragmentが互いに対話したい場合は、関連するActivityを通じて行う必要があります。2つのFragmentの間で直接メッセージをやり取りすることはできません。

インターフェースの定義

Fragmentとそれに関連するActivityの間でメッセージパッシングを行うには、Fragmentにインターフェースを定義し、Activityにそのインターフェースを実装すればよいのです。FragmentはonAttach()メソッドでActivityのインターフェースを取得し、インターフェースのメソッドを呼び出してActivityと通信を行います。

以下に、Fragmentの例としてHeadlinesFragment.javaを示します。

public class HeadlinesFragment extends ListFragment { 
    private OnFragmentInteractionListener mListener;
    public HeadlinesFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Define an array
        List<String> data = new ArrayList<String>();
        for (int i = 0; i < 30; i++) {
            data.add("smyh" + i);
        }
        //add the array to the ArrayAdapter
        ArrayAdapter adapter = new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1, data);
        //setListAdapter() interface, not ListView.setAdapter() or other methods
        setListAdapter(adapter);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        mListener.onFragmentInteraction(null);
    }
    ...
}


Fragmentはメンバ変数mListenerを持ち、mListenerのonFragmentInteraction()メソッドを呼び出すことで、Activityに情報を渡せるようになったことに注目してください。もちろん、インターフェースに他のメソッドがあれば、他のメソッドも呼び出すことができます。
例えば、ユーザがListの項目をクリックすると、Fragment内の以下のメソッドが実行されます。そして、このメソッド内でonFragmentInteraction()を呼び、Activityに情報を渡します。

fragment_headlines.xmlをレイアウトします。


Activityでインターフェイスを実装する

ActivityはFragmentから情報を受け取るために、OnFragmentInteractionListenerインターフェイスを実装する必要があります。ここには、onFragmentInteraction(Uri)というメソッドが一つだけあり、トーストを印刷するために実装します。(もちろん、OnFragmentInteractionListenerに複数のメソッドを定義し、それを実装することも可能です)
MainActivity.java。

public class MainActivity extends ActionBarActivity implements HeadlinesFragment.OnFragmentInteractionListener {
    private FragmentManager fm = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFragment();
    }

    private void initFragment() {
        HeadlinesFragment headlinesFragment = new HeadlinesFragment();

        fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.container,headlinesFragment);
        ft.commit();
    }


    @Override
    public void onFragmentInteraction(Uri uri) {
        Toast.makeText(this,"exchange,cornerfloor",Toast.LENGTH_LONG).show();
    }
    ...
}

activity_main.xml です。


結果は以下のようになり、ListViewのいずれかの項目がクリックされると、トーストがポップアップ表示されるようになりました。(FragmentのonListItemClickメソッドの中でOnFragmentInteractionListenerメソッドを呼び出しているので、このような結果になるのでしょう)

簡単に言うと、フラグメントはActivityに情報を渡したり、同じActivityにバインドされている別のフラグメントに情報を渡したりする必要があるのです。ActivityはFragmentのOnFragmentInteractionListenerインターフェイスを実装する必要があります。なぜなら、メッセージの受け渡しは、このインターフェースにあるメソッドを通じて意図的に行われるからです。