使用Fragment创建动态UI(3)-- 与其他Fragment通信
为了复用Fragment UI组件,你应该把它们创建成一个自包含的模块化组件即定义自己的布局和行为。一旦你定义了这些可复用的fragment,你可以把它们绑定到一个activity,然后把它们和整个应用的逻辑连接起来形成一个统一的组合UI。
你通常希望一个fragment能和另一个通信,例如根据用户事件改变内容。所有的fragment对fragment的通信都应该通过绑定的activity。两个fragment永远不应该直接通信。
定义一个界面
为了允许一个fragment可以和它的宿主activity通信,你应该在这个fragment类里定义一个接口,并且在activity里实现。这个fragment在它的生命周期方法onAttach()里捕获这个接口实现,然后可以调用这个接口方法来和activity通信。
下面就是一个fragment与activity通信的例子:
public class HeadlinesFragment extends ListFragment {
OnHeadlineSelectedListener mCallback;
// 宿主activity必须实现这个接口
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// 确保宿主activity实现了这个接口. 否则抛出异常
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
...
}
现在这个fragment可以使用onHeadlineSelectedListener这个接口的mCallback实例引用,调用onArticleSelected()方法(或者使用接口中的其它方法)向宿主activity发送消息
例如,当用户点击列表条目的时候,下面的方法就会被调用。这个fragment使用这个回调接口来向宿主activity发送事件。
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
// 向宿主activity发送事件
mCallback.onArticleSelected(position);
}
实现接口
为了从这个fragment收到事件回调,这个宿主activity必须实现定义在fragment类中的接口。
例如,下面的这个activity就实现了上个例子中定义的接口。
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
宿主activity可以通过方法findFragmentById()捕获一个fragment的实例,然后直接调用这个fragment的公共方法来向这个fragment发送消息。
例如,想像一下上例中定义的activity可能还包含另一个fragment,这个fragment是用来显示上面回调方法里的返回的数据指定的内容。在这种情况下,这个activity可以把从回调方法中获得的信息传递给需要显示的另一个fragment:
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) {
// 如果ArticlFragment存在, 说明我们使用了两面板布局...
// 直接调用 ArticleFragment的方法更新内容
articleFrag.updateArticleView(position);
} else {
//否则,我们使用了单面板布局,我们必须创建一个fragment,并且将要显示的文章作为参数传递进去
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// 替换fragment_container中的fragment,
// 添加事务到回退栈,这样用户可以回退事务
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// 提交事务
transaction.commit();
}
}
}
下载示例Demo