因为FragmentPagerAdapter内部存在缓存,因此调用notifyDataSetChanged()并不能够去更新Fragment的内容。
参考:http://www.devba.com/index.php/archives/5826.html
http://stackoverflow.com/questions/7263291/viewpager-pageradapter-not-updating-the-view/7287121#7287121
可以有两种解决办法:
(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 mDatas;
private List tagList = new ArrayList();
public FragmentViewPagerAdapter(FragmentManager fm, List 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 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 urls = new ArrayList();
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 tagList = new ArrayList();
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 mDatas;
public FragmentViewPagerAdapter(FragmentManager fm, List 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 datas){
this.mDatas = datas;
notifyDataSetChanged();
}
}
跟普通的用法一样,唯一的要求是,Fragment必须要实现UpdateAble接口,perfect!