ViewPager+Fragment切换时无法更新数据问题解析(源代码分享)
来源:互联网 发布:python搭建app服务器 编辑:程序博客网 时间:2024/05/04 14:53
在一个 Android 应用中,我们可以使用 FragmentPageAdapter 来处理多 Fragment 页面的横向滑动。但是当 Fragment 对应的数据集发生改变时,我们都希望能够通过调用 mAdapter.notifyDataSetChanged() 来触发 Fragment 页面使用新的数据调整或重新生成其内容,可是当我们使用 notifyDataSetChanged() 后,我们会发现这个方法不会生效。那为什么会这样呢,之前遇到了相同的问题一直没法解决,在网上给出的乱七八糟的答案感觉也不是正解,终于在今早彻底解决了这个问题。我们先来了解下FragmentPagerAdapter的源代码。
我们特别关注下以下这句
根据原代码我们可以知道系统给每一个Fragment都打上了一个标签,通过标签来寻找相应的fragment,所以当我们第二次进入fragment的时候,fragment的oncreate,oncreateView方法都不会被调用的,因为FragmentPageAdapter中的getitem()方法根本不会被调用,因为系统会根据标签找到相应的fragment,如果已经存在,就不会被调用,fragment有一个缓存机制在这里。那么如果我们一定要更新fragment,那么我们又该如何处理呢,我们就可以以其人之道,还治其人之身,我们可以通过tag标签找到我们相应的fragment,就可以对该fragment进行更新。那么我们现在就开始吧。
我们可以发现在queryFragment里也有一个update()方法,这个方法呢就是接下来我们用接口回掉机制更新我们相应fragment的要使用的方法,方法里的内容根据自己的需要编译就可以了。
之后比如我们在A Fragment 里头插入了数据,需要BFragment对该数据进行显示,那么我们现在AFragment的onAttach方法中
然后我们回到Activity实现该接口里的方法,更新BFragment界面
大功告成了,贴一下完整的MainAcitivity代码吧!
@Override public Object instantiateItem(ViewGroup container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); // Do we already have this fragment? 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都打上了一个标签,通过标签来寻找相应的fragment,所以当我们第二次进入fragment的时候,fragment的oncreate,oncreateView方法都不会被调用的,因为FragmentPageAdapter中的getitem()方法根本不会被调用,因为系统会根据标签找到相应的fragment,如果已经存在,就不会被调用,fragment有一个缓存机制在这里。那么如果我们一定要更新fragment,那么我们又该如何处理呢,我们就可以以其人之道,还治其人之身,我们可以通过tag标签找到我们相应的fragment,就可以对该fragment进行更新。那么我们现在就开始吧。
我们先来定义一个list<String> tagList 来存储一下tag
private List<String> tagList;第二部重写instantiateItem方法,把fragment对应的标签存储在taglist集合里
public Object instantiateItem(ViewGroup container, int position) { tagList.add(makeFragmentName(container.getId(), getItemId(position))); return super.instantiateItem(container, position); }makeFragmentName()是FragmentPageAdapter源码里打fragment标签的方法
public static String makeFragmentName(int viewId, int index) {return "android:switcher:" + viewId + ":" + index;}
第三步我们再adapter里自己写一个update()方法
public void update(int item) {Fragment fragment = fm.findFragmentByTag(tagList.get(item));if (fragment != null) {switch (item) {case 0:break;case 1:((QueryFragment) fragment).update();break;case 2:break;default:break;}}}
我们可以发现在queryFragment里也有一个update()方法,这个方法呢就是接下来我们用接口回掉机制更新我们相应fragment的要使用的方法,方法里的内容根据自己的需要编译就可以了。
好的现在万事具备只要实现fragment的数据更新问题就可以了,通过接口回掉机制来实现。
首先我们定义一个接口,让我们的主Activity来实现
public interface FragmentListener { public void onFragmentClickListener(int item); }
之后比如我们在A Fragment 里头插入了数据,需要BFragment对该数据进行显示,那么我们现在AFragment的onAttach方法中
public void onAttach(Activity activity) { super.onAttach(activity); try { listener = (FragmentListener)activity; } catch (Exception e) { e.printStackTrace(); } }然后对数据更新的时候,我们就在Afragment调用这个接口
if (listener != null) {listener.onFragmentClickListener(1);}
然后我们回到Activity实现该接口里的方法,更新BFragment界面
public void onFragmentClickListener(int item) {adapter.update(item);adapter.update(item);}
大功告成了,贴一下完整的MainAcitivity代码吧!
package com.example.account.main;import java.util.ArrayList;import java.util.List;import com.example.account.add.AddFragment;import com.example.account.query.QueryFragment;import com.example.account.setting.SettingFragment;import com.example.account.utils.PagerSlidingTabStrip;import com.melhc.xiji.R;import android.annotation.SuppressLint;import android.content.Intent;import android.graphics.Color;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentPagerAdapter;import android.support.v4.view.ViewPager;import android.util.DisplayMetrics;import android.util.TypedValue;import android.view.KeyEvent;import android.view.ViewGroup;import android.widget.Toast;public class MainActivity extends FragmentActivity implements FragmentListener{private MyPagerAdapter adapter;private AddFragment addFragment;private List<String> tagList;private SettingFragment settingFragment;private boolean isExit;private QueryFragment queryFragment;private ViewPager pager;private PagerSlidingTabStrip tabs;private FragmentManager fm;private DisplayMetrics dm;private List<Fragment> list;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);pager = (ViewPager) findViewById(R.id.pager);tabs = (PagerSlidingTabStrip) findViewById(R.id.tabs);initFragment();fm = getSupportFragmentManager();tagList = new ArrayList<String>();adapter = new MyPagerAdapter(fm);pager.setAdapter(adapter);tabs.setViewPager(pager);}public void initFragment() {list = new ArrayList<Fragment>();addFragment = new AddFragment();queryFragment = new QueryFragment();settingFragment = new SettingFragment();list.add(addFragment);list.add(queryFragment);list.add(settingFragment);}public class MyPagerAdapter extends FragmentPagerAdapter {public MyPagerAdapter(FragmentManager fm) {super(fm);}private final String[] titles = { "1", "2", "3" };@Overridepublic CharSequence getPageTitle(int position) {return titles[position];}@Overridepublic int getCount() {return titles.length;}@Overridepublic Fragment getItem(int position) {return list.get(position);}public Object instantiateItem(ViewGroup container, int position) {tagList.add(makeFragmentName(container.getId(),(int) getItemId(position)));return super.instantiateItem(container, position);}public void update(int item) {Fragment fragment = fm.findFragmentByTag(tagList.get(item));if (fragment != null) {switch (item) {case 0:break;case 1:((QueryFragment) fragment).update();break;case 2:break;default:break;}}}}public static String makeFragmentName(int viewId, int index) {return "android:switcher:" + viewId + ":" + index;}public void onFragmentClickListener(int item) {adapter.update(item);adapter.update(item);}}
5 0
- ViewPager+Fragment切换时无法更新数据问题解析(源代码分享)
- Viewpager+fragment数据更新问题解析
- Viewpager+fragment数据更新问题解析
- Viewpager+fragment数据更新问题解析
- Viewpager+fragment数据更新问题
- ViewPager切换Fragment时ListView数据不更新
- Android-ViewPager+Fragment数据更新问题
- Fragment嵌套ViewPager切换后数据消失ViewPager空白问题
- Fragment嵌套ViewPager切换后数据消失ViewPager空白问题
- Fragment嵌套ViewPager切换后数据消失ViewPager空白问题
- Fragment嵌套ViewPager切换后数据消失ViewPager空白问题
- Viewpager+Fragment 数据更新
- ViewPager嵌套Fragment切换Fragment时不更新页面
- [笔记]关于fragment切换更新数据问题
- 关于fragment切换更新数据问题
- 【问题】viewpager创建fragment时 数据需要切换fragment多次才能在listview显示
- viewpager切换fragment时崩溃问题
- Fragment与ViewPager之间更新数据相关问题
- Linux成为只读模式解决办法
- js实现简单自定义导航,导航随项目id变化(ECMS下内容页修改)
- 长沙农天农业科技有限公司人口过亿的国家
- zoj 1721 (bellmanford)
- 016:hibernate基础配置
- ViewPager+Fragment切换时无法更新数据问题解析(源代码分享)
- 解决oj题目内部测试数据解压乱码的问题
- SetWindowsHookEx详解
- 每个人都是幸福的。只是,你的幸福,常常在别人眼里。
- 树莓派实战实例(三)系统设置
- (无bug版)有一字符串,包含数字与字母,编程去除数字。要求: vae123rcly //要求在原字符串中操作 //使用指针处理
- Nginx的事件处理机制
- Julia的学习资料从哪里找?
- (并查集)B - Friends(8.4.1)