标签:
因为FragmentPagerAdapter内部存在缓存,因此调用notifyDataSetChanged()并不能够去更新Fragment的内容。
参考:http://www.devba.com/index.php/archives/5826.html
可以有两种解决办法:
(1)重写Adapter的getItemPosition():
public int getItemPosition(Object object) { return POSITION_NONE; }当调用notifyDataSetChanged()的时候,ViewPager会remove掉所有的view,然后重新去加载。可行,但是效率低。
(2)在view上调用SetTag,然后用ViewPager.findViewWithTag()来找到要更新的view,然后做更新。
因为FragmentPagerAdapter内部缓存Fragment的时候,已经是按照tag的方式缓存的,因此,在更新的时候,我们只要根据tag,拿到fragment,然后去更新fragment就可以了。
看下FragmentPagerAdapter的instantiateItem()方法:
public Object instantiateItem(ViewGroup container, int position) { if (this.mCurTransaction == null) { this.mCurTransaction = this.mFragmentManager.beginTransaction(); } long itemId = getItemId(position); String name = makeFragmentName(container.getId(), itemId);//这里就是在生成fragment的tag Fragment fragment = this.mFragmentManager.findFragmentByTag(name);//这里是根据tag查找 if (fragment != null) { this.mCurTransaction.attach(fragment);//找到直接attch } else { fragment = getItem(position);//找不到的时候,才会调用getItem this.mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } if (fragment != this.mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; }根据原代码我们可以知道系统给每一个Fragment都打上了一个标签,通过标签来寻找相应的fragment,所以当我们第二次进入fragment的时候,fragment的oncreate,oncreateView方法都不会被调用的,因为FragmentPageAdapter中的getitem()方法根本不会被调用,因为系统会根据标签找到相应的fragment,如果已经存在,就不会被调用,fragment有一个缓存机制在这里。
public class FragmentViewPagerAdapter extends FragmentPagerAdapter { private FragmentManager mFragmentManager; private List<String> mDatas; private List<String> tagList = new ArrayList<String>(); public FragmentViewPagerAdapter(FragmentManager fm, List<String> datas) { super(fm); this.mFragmentManager = fm; this.mDatas = datas; } @Override public Object instantiateItem(ViewGroup container, int position) { tagList.add(makeFragmentName(container.getId(), getItemId(position))); //把tag存起来 return super.instantiateItem(container, position); } @Override public void destroyItem(ViewGroup container, int position, Object object){ super.destroyItem(container, position, object); tagList.remove(makeFragmentName(container.getId(), getItemId(position)));//把tag删掉 } @Override public Fragment getItem(int position) { String url = mDatas.get(position); WebViewFragmentV4 webview = new WebViewFragmentV4(url);//本文测试的Fragment是一个WebViewFragment
return webview; } @Override public int getCount() { if (mDatas == null) { return 0; } else { return mDatas.size(); } } public void update(List<String> datas){ this.mDatas = datas; notifyDataSetChanged();//并不能起到更新Fragment内容的作用。 } public void update(int position){//这个事真正的更新Fragment的内容 WebViewFragmentV4 fragment = (WebViewFragmentV4)mFragmentManager.findFragmentByTag(tagList.get(position)); if(fragment == null){ return; } fragment.update(); } private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; } }WebViewFragmentV4.java:
public class WebViewFragmentV4 extends Fragment { private WebView mWebView; private boolean mIsWebViewAvailable; private String mUrl; public WebViewFragmentV4(String url) { this.mUrl = url; } /** * Called to instantiate the view. Creates and returns the WebView. */ @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (mWebView != null) { mWebView.destroy(); } mWebView = new WebView(getActivity()); mWebView.getSettings().setUseWideViewPort(true); mWebView.getSettings().setLoadWithOverviewMode(true); mWebView.setWebViewClient(new MyWebViewClient()); mWebView.loadUrl(mUrl); mIsWebViewAvailable = true; return mWebView; } /** * Called when the fragment is visible to the user and actively running. * Resumes the WebView. */ @Override public void onPause() { super.onPause(); mWebView.onPause(); } /** * Called when the fragment is no longer resumed. Pauses the WebView. */ @Override public void onResume() { mWebView.onResume(); super.onResume(); } /** * Called when the WebView has been detached from the fragment. The WebView * is no longer available after this time. */ @Override public void onDestroyView() { mIsWebViewAvailable = false; super.onDestroyView(); } /** * Called when the fragment is no longer in use. Destroys the internal state * of the WebView. */ @Override public void onDestroy() { if (mWebView != null) { mWebView.destroy(); mWebView = null; } super.onDestroy(); } public void update(){ if (mWebView != null) { mWebView.reload(); } } /** * Gets the WebView. */ public WebView getWebView() { return mIsWebViewAvailable ? mWebView : null; } private static class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); } } }
转载请标明出处:http://blog.csdn.net/goldenfish1919/article/details/47661443
测试代码:
//1. 初始化 viewpager = (ViewPager)this.findViewById(R.id.viewpager); adapter = new FragmentViewPagerAdapter(getSupportFragmentManager(), null); viewpager.setAdapter(adapter); //2. 加载数据 List<String> urls = new ArrayList<String>(); urls.add("http://172.16.28.253:8080/web/1.jsp"); urls.add("http://172.16.28.253:8080/web/2.jsp"); urls.add("http://172.16.28.253:8080/web/3.jsp"); urls.add("http://172.16.28.253:8080/web/4.jsp"); adapter.update(urls); //3. 做更新 Button update = (Button) this.findViewById(R.id.update); update.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(viewpager != null && adapter != null){ viewpager.setCurrentItem(3, true); adapter.update(3);//重新加载position是3的页面 } } });
重构一下:
(1)BaseFragmentPagerAdapter.java
public abstract class BaseFragmentPagerAdapter extends FragmentPagerAdapter{ private FragmentManager mFragmentManager; private List<String> tagList = new ArrayList<String>(); public BaseFragmentPagerAdapter(FragmentManager fm) { super(fm); this.mFragmentManager = fm; } @Override public Object instantiateItem(ViewGroup container, int position) { tagList.add(makeFragmentName(container.getId(), getItemId(position))); return super.instantiateItem(container, position); } @Override public void destroyItem(ViewGroup container, int position, Object object){ super.destroyItem(container, position, object); tagList.remove(makeFragmentName(container.getId(), getItemId(position))); } private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; } public void update(int position){ Fragment fragment = (Fragment)mFragmentManager.findFragmentByTag(tagList.get(position)); if(fragment == null){ return; } if(fragment instanceof UpdateAble){//这里唯一的要求是Fragment要实现UpdateAble接口 ((UpdateAble)fragment).update(); } } public interface UpdateAble { public void update(); } }以后我们的Adapter只要继承BaseFragmentPagerAdapter就可以了,比如:
(2)FragmentViewPagerAdapter.java
public class FragmentViewPagerAdapter extends BaseFragmentPagerAdapter { private List<String> mDatas; public FragmentViewPagerAdapter(FragmentManager fm, List<String> datas) { super(fm); this.mDatas = datas; } @Override public Fragment getItem(int position) { String url = mDatas.get(position); WebViewFragmentV4 webview = new WebViewFragmentV4(url); return webview; } @Override public int getCount() { if (mDatas == null) { return 0; } else { return mDatas.size(); } } public void update(List<String> datas){ this.mDatas = datas; notifyDataSetChanged(); } }跟普通的用法一样,唯一的要求是,Fragment必须要实现UpdateAble接口,perfect!
版权声明:本文为博主原创文章,未经博主允许不得转载。
Android-ViewPager+Fragment数据更新问题
标签:
原文地址:http://blog.csdn.net/goldenfish1919/article/details/47661443