正文
尽管 Fragment
作为独立于 FragmentActivity
的对象实现,并且可在多个 Activity 内使用,但Fragment的给定实例会直接绑定到托管该Fragment的 Activity上。
具体而言,Fragment可通过 getActivity()
访问 FragmentActivity
实例,并轻松执行在 Activity 布局中查找视图等任务:
View listView = getActivity().findViewById(R.id.list);
同样,在 Activity 中也可使用 findFragmentById()
或 findFragmentByTag()
,通过从 FragmentManager
获取对 Fragment
的引用来调用Fragment中的方法。例如:
ExampleFragment fragment = (ExampleFragment) getSupportFragmentManager().findFragmentById(R.id.example_fragment);
下一步就是在Activity中需要创建事件回调:
在某些情况下,可能需使用Fragment来与 Activity 或 Activity 托管的其他Fragment共享事件或数据。如要共享数据,请依照 ViewModel 指南中“在Fragment之间共享数据”部分所述,创建共享的 ViewModel。如需传播无法使用 ViewModel 处理的事件,则可改为在Fragment内定义回调接口,并要求宿主 Activity 实现此接口。当 Activity 通过该接口收到回调时,可根据需要与布局中的其他Fragment共享这些信息。
例如,如果某个新闻应用的 Activity 有两个Fragment,其中一个用于显示文章列表(Fragment A),另一个用于显示文章(Fragment B),则Fragment A 必须在列表项被选定后告知 Activity,以便它告知Fragment B 显示该文章。在本例中,OnArticleSelectedListener
接口在Fragment A 内进行声明:
public static class FragmentA extends ListFragment { ... // Container Activity must implement this interface public interface OnArticleSelectedListener { public void onArticleSelected(Uri articleUri); } ...}
然后该Fragment的宿主 Activity 会实现 OnArticleSelectedListener
接口并重写 onArticleSelected()
,将来自Fragment A 的事件通知Fragment B。为确保宿主 Activity 实现此接口,Fragment A 的 onAttach()
回调方法(系统在向 Activity 添加Fragment时调用的方法)会通过转换传递到 onAttach()
中的 Activity
来实例化 OnArticleSelectedListener
的实例:
public static class FragmentA extends ListFragment { OnArticleSelectedListener listener; ... @Override public void onAttach(Context context) { super.onAttach(context); try { listener = (OnArticleSelectedListener) context; } catch (ClassCastException e) { throw new ClassCastException(context.toString() + " must implement OnArticleSelectedListener"); } } ...}
如果 Activity 未实现接口,则Fragment会抛出 ClassCastException
。若实现成功,mListener
成员会保留对 Activity 的 OnArticleSelectedListener
实现的引用,以便Fragment A 可通过调用 OnArticleSelectedListener
接口定义的方法与 Activity 共享事件。例如,如果Fragment A 是 ListFragment
的一个扩展,则用户每次点击列表项时,系统都会调用Fragment中的 onListItemClick()
,然后该方法会通过调用 onArticleSelected()
与 Activity 共享事件:
public static class FragmentA extends ListFragment { OnArticleSelectedListener listener; ... @Override public void onListItemClick(ListView l, View v, int position, long id) { // Append the clicked item's row ID with the content provider Uri Uri noteUri = ContentUris.withAppendedId(ArticleColumns.CONTENT_URI, id); // Send the event and Uri to the host activity listener.onArticleSelected(noteUri); } ...}
传递到 onListItemClick()
的 id
参数是被点击项的行 ID,即 Activity(或其他Fragment)用来从应用的 ContentProvider
获取文章的 ID。