现在的位置: 首页 > 综合 > 正文

Fragment与Activity的通讯

2013年12月09日 ⁄ 综合 ⁄ 共 3032字 ⁄ 字号 评论关闭

在使用fragment的时候,通常的用法都是使用一个activity来管理不同的fragment,所以每个fragment与activity的及时通讯就很重要。

1、Fragment可以调用getActivity()方法很容易的得到它所在的activity的对象,然后就可以查找activity中的控件们(findViewById())。例如:

Viewlist View =getActivity().findViewById(R.id.list);

同样的,activity也可以通过FragmentManager的方法查找它所包含的frament们。例如:

ExampleFragment fragment =(ExampleFragment)getFragmentManager().findFragmentById(R.id.example_fragment)

但是这个并不是最好的办法,根据fragmen的定义,我们可以在fragment里面定义一个回调接口,在activity中实现它。举个谷歌官方给的例子,这是一个新闻程序的例子,它有一个activity,activity中含有两个fragment。fragmentA显示新闻标题,fragmentB显示标题对应的内容。fragmentA必须在用户选择了某个标题时告诉activity,然后activity再告诉fragmentB,fragmentB就显示出对应的内容(为什么这么麻烦?直接fragmentA告诉fragmentB不就行了?也可以啊,但是你的fragment就减少了可重用的能力。现在我只需把我的事件告诉宿主,由宿主决定如何处置,这样是不是重用性更好呢?)。如下例:

public class PersionListFragment extends ListFragment {
    private static final String STATE_ACTIVATED_POSITION = "activated_position";
    private Callbacks mCallbacks = sDummyCallbacks;
    private int mActivatedPosition = ListView.INVALID_POSITION;
    public interface Callbacks {
        public void onItemSelected(String id);
    }
    private static Callbacks sDummyCallbacks = new Callbacks() {
        @Override
        public void onItemSelected(String id) {
        }
    };

我们在PersionListFragment中定义了mCallbacks这个接口,当然了我们自己实现了一个空的接口内容sDummyCallbacks,当作mCallbacks的默认接口。
下面就是我们要到Activity中去实现这个接口:

public class PersionListActivity extends FragmentActivity implements PersionListFragment.Callbacks {
	private boolean mTwoPane;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_persion_twopane);
		if (findViewById(R.id.persion_detail_container) != null) {
			mTwoPane = true;
			((PersionListFragment) getSupportFragmentManager().findFragmentById(R.id.persion_list)).setActivateOnItemClick(false);
		}
	}

	@Override
	public void onItemSelected(String id) {
		if (mTwoPane) {
			Bundle arguments = new Bundle();
			arguments.putString(PersionDetailFragment.ARG_ITEM_ID, id);
			PersionDetailFragment fragment = new PersionDetailFragment();
			fragment.setArguments(arguments);
			getSupportFragmentManager().beginTransaction().replace(R.id.persion_detail_container, fragment).commit();
		} else {
			Intent detailIntent = new Intent(this, PersionDetailActivity.class);
			detailIntent.putExtra(PersionDetailFragment.ARG_ITEM_ID, id);
			startActivity(detailIntent);
		}
	}
}

那么实现完了接口怎么传给刚才的fragment呢?
当fragment添加到activity中时,会调用fragment的方法onAttach(),这个方法中适合检查activity是否实现了OnArticleSelectedListener接口,检查方法就是对传入的activity的实例进行类型转换,然后赋值给我们在fragment中定义的接口。

 @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (!(activity instanceof Callbacks)) {
            throw new IllegalStateException("Activity must implement fragment's callbacks.");
        }
        mCallbacks = (Callbacks) activity;
    }


    @Override
    public void onDetach() {
        super.onDetach();
        mCallbacks = sDummyCallbacks;
    }


    @Override
    public void onListItemClick(ListView listView, View view, int position, long id) {
        super.onListItemClick(listView, view, position, id);
        mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
    }

在一个fragment从activity中剥离的时候,就会调用onDetach方法,这个时候正好可以把它的接口恢复为默认接口。防止不必要的错误。注意看onAttach方法中的代码,在赋值之前要做一个判断,看看Activity中有没有实现了这个接口,用到了instanceof。如果没有实现接口,我们就抛出异常。

这个时候我们就实现了Fragment与Activity之间的通讯,把主要的事情还是都交给管理员Activity做比较好。
代码下载在评论上

【上篇】
【下篇】

抱歉!评论已关闭.