Android-ViewPager+Fragment数据更新问题

因为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():

  1. public int getItemPosition(Object object) {  
  2.     return POSITION_NONE;  
  3. }  
当调用notifyDataSetChanged()的时候,ViewPager会remove掉所有的view,然后重新去加载。可行,但是效率低。

(2)在view上调用SetTag,然后用ViewPager.findViewWithTag()来找到要更新的view,然后做更新。

因为FragmentPagerAdapter内部缓存Fragment的时候,已经是按照tag的方式缓存的,因此,在更新的时候,我们只要根据tag,拿到fragment,然后去更新fragment就可以了。

看下FragmentPagerAdapter的instantiateItem()方法:

  1. public Object instantiateItem(ViewGroup container, int position)  
  2.   {  
  3.     if (this.mCurTransaction == null) {  
  4.       this.mCurTransaction = this.mFragmentManager.beginTransaction();  
  5.     }  
  6.   
  7.     long itemId = getItemId(position);  
  8.   
  9.     String name = makeFragmentName(container.getId(), itemId);//这里就是在生成fragment的tag  
  10.     Fragment fragment = this.mFragmentManager.findFragmentByTag(name);//这里是根据tag查找  
  11.     if (fragment != null)  
  12.     {  
  13.       this.mCurTransaction.attach(fragment);//找到直接attch  
  14.     } else {  
  15.       fragment = getItem(position);//找不到的时候,才会调用getItem  
  16.   
  17.       this.mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId));  
  18.     }  
  19.   
  20.     if (fragment != this.mCurrentPrimaryItem) {  
  21.       fragment.setMenuVisibility(false);  
  22.       fragment.setUserVisibleHint(false);  
  23.     }  
  24.   
  25.     return fragment;  
  26.   }  
根据原代码我们可以知道系统给每一个Fragment都打上了一个标签,通过标签来寻找相应的fragment,所以当我们第二次进入fragment的时候,fragment的oncreate,oncreateView方法都不会被调用的,因为FragmentPageAdapter中的getitem()方法根本不会被调用,因为系统会根据标签找到相应的fragment,如果已经存在,就不会被调用,fragment有一个缓存机制在这里。
现在的问题是必须要做更新,那么可以这么弄:
  1. public class FragmentViewPagerAdapter extends FragmentPagerAdapter {  
  2.       
  3.     private FragmentManager mFragmentManager;  
  4.     private List<String> mDatas;  
  5.     private List<String> tagList = new ArrayList<String>();  
  6.   
  7.     public FragmentViewPagerAdapter(FragmentManager fm, List<String> datas) {  
  8.         super(fm);  
  9.         this.mFragmentManager = fm;  
  10.         this.mDatas = datas;  
  11.     }  
  12.       
  13.     @Override  
  14.     public Object instantiateItem(ViewGroup container, int position) {      
  15.         tagList.add(makeFragmentName(container.getId(), getItemId(position))); //把tag存起来     
  16.         return super.instantiateItem(container, position);      
  17.     }   
  18.       
  19.     @Override  
  20.     public void destroyItem(ViewGroup container, int position, Object object){  
  21.         super.destroyItem(container, position, object);  
  22.         tagList.remove(makeFragmentName(container.getId(), getItemId(position)));//把tag删掉  
  23.     }  
  24.       
  25.     @Override  
  26.     public Fragment getItem(int position) {  
  27.         String url = mDatas.get(position);  
  28.         WebViewFragmentV4 webview = new WebViewFragmentV4(url);//本文测试的Fragment是一个WebViewFragment  
  1.         return webview;  
  2.     }  
  3.   
  4.     @Override  
  5.     public int getCount() {  
  6.         if (mDatas == null) {  
  7.             return 0;  
  8.         } else {  
  9.             return mDatas.size();  
  10.         }  
  11.     }  
  12.   
  13.     public void update(List<String> datas){  
  14.         this.mDatas = datas;  
  15.         notifyDataSetChanged();//并不能起到更新Fragment内容的作用。  
  16.     }  
  17.       
  18.     public void update(int position){//这个事真正的更新Fragment的内容  
  19.         WebViewFragmentV4 fragment = (WebViewFragmentV4)mFragmentManager.findFragmentByTag(tagList.get(position));    
  20.         if(fragment == null){  
  21.             return;  
  22.         }  
  23.         fragment.update();  
  24.     }  
  25.   
  26.     private static String makeFragmentName(int viewId, long id) {  
  27.         return "android:switcher:" + viewId + ":" + id;  
  28.     }  
  29. }  
WebViewFragmentV4.java:
  1. public class WebViewFragmentV4 extends Fragment {  
  2.     private WebView mWebView;  
  3.     private boolean mIsWebViewAvailable;  
  4.     private String mUrl;  
  5.     public WebViewFragmentV4(String url) {  
  6.         this.mUrl = url;  
  7.     }  
  8.   
  9.     /** 
  10.      * Called to instantiate the view. Creates and returns the WebView. 
  11.      */  
  12.     @Override  
  13.     public View onCreateView(LayoutInflater inflater, ViewGroup container,  
  14.             Bundle savedInstanceState) {  
  15.         if (mWebView != null) {  
  16.             mWebView.destroy();  
  17.         }  
  18.         mWebView = new WebView(getActivity());  
  19.         mWebView.getSettings().setUseWideViewPort(true);  
  20.         mWebView.getSettings().setLoadWithOverviewMode(true);   
  21.         mWebView.setWebViewClient(new MyWebViewClient());  
  22.         mWebView.loadUrl(mUrl);  
  23.         mIsWebViewAvailable = true;  
  24.         return mWebView;  
  25.     }  
  26.   
  27.     /** 
  28.      * Called when the fragment is visible to the user and actively running. 
  29.      * Resumes the WebView. 
  30.      */  
  31.     @Override  
  32.     public void onPause() {  
  33.         super.onPause();  
  34.         mWebView.onPause();  
  35.     }  
  36.   
  37.     /** 
  38.      * Called when the fragment is no longer resumed. Pauses the WebView. 
  39.      */  
  40.     @Override  
  41.     public void onResume() {  
  42.         mWebView.onResume();  
  43.         super.onResume();  
  44.     }  
  45.   
  46.     /** 
  47.      * Called when the WebView has been detached from the fragment. The WebView 
  48.      * is no longer available after this time. 
  49.      */  
  50.     @Override  
  51.     public void onDestroyView() {  
  52.         mIsWebViewAvailable = false;  
  53.         super.onDestroyView();  
  54.     }  
  55.   
  56.     /** 
  57.      * Called when the fragment is no longer in use. Destroys the internal state 
  58.      * of the WebView. 
  59.      */  
  60.     @Override  
  61.     public void onDestroy() {  
  62.         if (mWebView != null) {  
  63.             mWebView.destroy();  
  64.             mWebView = null;  
  65.         }  
  66.         super.onDestroy();  
  67.     }  
  68.   
  69.     public void update(){  
  70.         if (mWebView != null) {  
  71.             mWebView.reload();  
  72.         }  
  73.     }  
  74.       
  75.     /** 
  76.      * Gets the WebView. 
  77.      */  
  78.     public WebView getWebView() {  
  79.         return mIsWebViewAvailable ? mWebView : null;  
  80.     }  
  81.       
  82.     private static class MyWebViewClient extends WebViewClient {  
  83.           
  84.         @Override  
  85.         public boolean shouldOverrideUrlLoading(WebView view, String url) {  
  86.             view.loadUrl(url);  
  87.             return true;  
  88.         }  
  89.   
  90.         @Override  
  91.         public void onPageStarted(WebView view, String url, Bitmap favicon) {  
  92.             super.onPageStarted(view, url, favicon);  
  93.         }  
  94.           
  95.         @Override  
  96.         public void onPageFinished(WebView view, String url) {  
  97.             super.onPageFinished(view, url);  
  98.         }  
  99.   
  100.         @Override  
  101.         public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {  
  102.             super.onReceivedError(view, errorCode, description, failingUrl);  
  103.         }  
  104.     }  
  105. }  

转载请标明出处:http://blog.csdn.net/goldenfish1919/article/details/47661443

测试代码:

  1. //1. 初始化  
  2. viewpager = (ViewPager)this.findViewById(R.id.viewpager);  
  3. adapter = new FragmentViewPagerAdapter(getSupportFragmentManager(), null);  
  4. viewpager.setAdapter(adapter);  
  5. //2. 加载数据  
  6. List<String> urls = new ArrayList<String>();  
  7. urls.add("http://172.16.28.253:8080/web/1.jsp");  
  8. urls.add("http://172.16.28.253:8080/web/2.jsp");  
  9. urls.add("http://172.16.28.253:8080/web/3.jsp");  
  10. urls.add("http://172.16.28.253:8080/web/4.jsp");  
  11. adapter.update(urls);  
  12. //3. 做更新  
  13. Button update = (Button) this.findViewById(R.id.update);  
  14. update.setOnClickListener(new View.OnClickListener() {  
  15.     @Override  
  16.     public void onClick(View v) {  
  17.         if(viewpager != null && adapter != null){  
  18.             viewpager.setCurrentItem(3true);  
  19.             adapter.update(3);//重新加载position是3的页面  
  20.         }  
  21.     }  
  22. });  

重构一下:

(1)BaseFragmentPagerAdapter.java

  1. public abstract class BaseFragmentPagerAdapter extends FragmentPagerAdapter{  
  2.       
  3.     private FragmentManager mFragmentManager;  
  4.     private List<String> tagList = new ArrayList<String>();  
  5.       
  6.     public BaseFragmentPagerAdapter(FragmentManager fm) {  
  7.         super(fm);  
  8.         this.mFragmentManager = fm;  
  9.     }  
  10.       
  11.     @Override  
  12.     public Object instantiateItem(ViewGroup container, int position) {      
  13.         tagList.add(makeFragmentName(container.getId(), getItemId(position)));      
  14.         return super.instantiateItem(container, position);      
  15.     }   
  16.       
  17.     @Override  
  18.     public void destroyItem(ViewGroup container, int position, Object object){  
  19.         super.destroyItem(container, position, object);  
  20.         tagList.remove(makeFragmentName(container.getId(), getItemId(position)));  
  21.     }  
  22.       
  23.     private static String makeFragmentName(int viewId, long id) {  
  24.         return "android:switcher:" + viewId + ":" + id;  
  25.     }  
  26.       
  27.     public void update(int position){  
  28.         Fragment fragment = (Fragment)mFragmentManager.findFragmentByTag(tagList.get(position));    
  29.         if(fragment == null){  
  30.             return;  
  31.         }  
  32.         if(fragment instanceof UpdateAble){//这里唯一的要求是Fragment要实现UpdateAble接口  
  33.             ((UpdateAble)fragment).update();  
  34.         }  
  35.     }  
  36.       
  37.     public interface UpdateAble {  
  38.         public void update();  
  39.     }  
  40. }  
以后我们的Adapter只要继承BaseFragmentPagerAdapter就可以了,比如:

(2)FragmentViewPagerAdapter.java

  1. public class FragmentViewPagerAdapter extends BaseFragmentPagerAdapter {  
  2.       
  3.     private List<String> mDatas;  
  4.   
  5.     public FragmentViewPagerAdapter(FragmentManager fm, List<String> datas) {  
  6.         super(fm);  
  7.         this.mDatas = datas;  
  8.     }  
  9.   
  10.     @Override  
  11.     public Fragment getItem(int position) {  
  12.         String url = mDatas.get(position);  
  13.         WebViewFragmentV4 webview = new WebViewFragmentV4(url);  
  14.         return webview;  
  15.     }  
  16.   
  17.     @Override  
  18.     public int getCount() {  
  19.         if (mDatas == null) {  
  20.             return 0;  
  21.         } else {  
  22.             return mDatas.size();  
  23.         }  
  24.     }  
  25.   
  26.     public void update(List<String> datas){  
  27.         this.mDatas = datas;  
  28.         notifyDataSetChanged();  
  29.     }  
  30. }  
跟普通的用法一样,唯一的要求是,Fragment必须要实现UpdateAble接口,perfect!
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值