• 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():

    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!




  • 相关阅读:
    技术列表
    常用软件开发工具
    EXCEL数据导入SQL2008相关操作
    点点滴滴
    揪出ASP.NET 2.0四大“插件”的总后台 ASPNETDB
    古人说
    好点子都是偷来的:史上最感性的60堂创新课读书摘要
    我是怎么割韭菜的:一个骗子的悔过与自白读书摘要
    人生如我读书摘要
    德米安:彷徨少年时读书摘要
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/7086657.html
Copyright © 2020-2023  润新知