最近做东西发现了一个问题,用viewPager加载Fragment,无法通过notifyDataSetChanged()进行数据更新,o(╯□╰)o很是郁闷。所以就研究了一番,以下是成果,分享一下
PagerAdapter的工作机制 可以参考一下这篇文章,我也是通过这篇文章得到的启发,在此表示感谢,O(∩_∩)O哈哈~
PagerAdapter主要的工作机制,就是会自动加载,及 卸载view,保留当前及相邻的view,共三个界面
接下来我们来说一下问题
1、如何通过外部点击事件(比如:actionbar),更新ViewPager里的信息
上面链接的博主,提供了一个方案是,重写instantiateItem,当然这也是一种方案。
重写多麻烦呀,我顺便看了一下源码,FragmentPagerAdapter里是这样写的
- @Override
- public Object instantiateItem(ViewGroup container, int position) {
- if (mCurTransaction == null) {
- mCurTransaction = mFragmentManager.beginTransaction();
- }
-
- final long itemId = getItemId(position);
-
-
- String name = makeFragmentName(container.getId(), itemId);
- Fragment fragment = mFragmentManager.findFragmentByTag(name);
- if (fragment != null) {
- if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
- mCurTransaction.attach(fragment);
- } else {
- fragment = getItem(position);
- if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
- mCurTransaction.add(container.getId(), fragment,
- makeFragmentName(container.getId(), itemId));
- }
- if (fragment != mCurrentPrimaryItem) {
- fragment.setMenuVisibility(false);
- fragment.setUserVisibleHint(false);
- }
-
- return fragment;
- }
里面有这么俩句
- String name = makeFragmentName(container.getId(), itemId);
- Fragment fragment = mFragmentManager.findFragmentByTag(name);
也就是说,给每个fragment都打上了一个tag,如果我们知道了tag,就可以通过tag 来获取Fragment,好的,按着这一个思路,我是这么来实现的
- public Object instantiateItem(ViewGroup container, int position) {
- tagList.add(makeFragmentName(container.getId(), getItemId(position)));
- return super.instantiateItem(container, position);
- }
我们来定义一个list<String> tagList 来存储一下tag,然后再adapter里加一个Update方法,如下
- public void update(int item){
- Fragment fragment = fm.findFragmentByTag(tagList.get(item));
- if(fragment != null){
- switch (item) {
- case 0:
- ((FirstFragment) fragment).update();
- break;
- case 1:
- ((SecondFragment) fragment).update();
- break;
- case 2:
- ((ThirdFragment) fragment).update();
- break;
- default:
- break;
- }
- }
- }
细心的朋友可能发现了,fragment有了一个update方法,这个其实个人加的,也就是通过tag获取到相应的fragment,然后调用fragment里的一个方法
fragment里的 方法就按自己的需求来了,我是这么写的,显示出当前的时间来
- public void update(){
- SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss",Locale.getDefault());
- mTextView.setText(format.format(new Date()));
- }
好了,一切搞定,我们就可以在外部的点击事件里通过mAdapter.update()方法来更新相应的fragment了,以下是效果图,点击ActionBar的Update就可以更新section2的时间了
O(∩_∩)O哈哈~,好吧,我暴露了,截图上有个按钮,那就是我们接下来要讨论的问题了
2、fragment之间的数据更新问题
1)首先,我们知道一件事情,现在activity可以向fragment传值了。我们可以借助这个来实现fragment之间的数据更新,流程是这样的
fragment -> activity -> fragment
o(╯□╰)o不会画图,就用文字代替了,敬请原谅,请各位将就着看吧。
2)我们来定义一个接口,让我们当前的activity来实现这个接口
- public interface FragmentListener {
-
- public void onFragmentClickListener(int item);
- }
3)在Fragment中,重写一下onAttach
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- try {
- listener = (FragmentListener)activity;
- } catch (Exception e) {
- e.printStackTrace();
- Log.i("", "activity 没有实现FragmentListener接口");
- }
- }
4)这样,我们拿到了FragmentListener,就可以通过回调来调用activity了
- mButton.setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- if(listener != null){
- listener.onFragmentClickListener(0);
- }
- }
- });
5)我们在activity里实现FragmentListener接口
- public void onFragmentClickListener(int item) {
- mSectionsPagerAdapter.update(item);
- }
就这样,我们就可以实现Fragment之间的数据更新问题了。
上面的截图中,点击section2里的按钮,就可以在section1中显示当前时间了,O(∩_∩)O哈哈~
tracymac7
死烤鹅
猴子搬来的救兵WooYun
qq_19257157
很多圈
_陈龙飞
JimiChen0
shadow066
如果是在嵌套Fragment的Activity里弹出来的话,那首先在Activity里通过getFragmentManager().findFragmentByTag()获取此Fragment,然后调用Fragment里的Refresh方法
xoxo4326
极客公园
shadow066
kikyou321
kikyou321
kikyou321
kikyou321
shadow066
就简单的写了一下思想,只要理解了思想应该问题就不大了