博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android-ViewPager+Fragment数据更新问题
阅读量:7120 次
发布时间:2019-06-28

本文共 8150 字,大约阅读时间需要 27 分钟。

由于FragmentPagerAdapter内部存在缓存。因此调用notifyDataSetChanged()并不可以去更新Fragment的内容。

參考:

能够有两种解决的方法:

(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);		}	}}

转载请标明出处:

測试代码:

//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!

你可能感兴趣的文章
Thinkphp 公共函数自动加载
查看>>
Linux内核之数据双链表
查看>>
【云计算的1024种玩法】巧用迁云工具轻松实现服务器迁移到ECS
查看>>
MaxCompute,基于Serverless的高可用大数据服务
查看>>
Linux下MySQL表名区分大小写
查看>>
mysql主从配置
查看>>
《算法图解》之散列表
查看>>
golang for switch break 使用
查看>>
PHP自己实现var_dump函数
查看>>
A simple poem
查看>>
故事板控件无法和代码关联的问题解决
查看>>
锁分段技术、ConcurrentHashMap、扩容
查看>>
恭喜51CTO视频课程认证讲师、博主李海园喜得姐妹花
查看>>
我的友情链接
查看>>
DNS resource record的写法
查看>>
Flash知识点总结
查看>>
三层交换的测试1:级联的傻HUB
查看>>
手动添加linux用户
查看>>
Android Unable to execute dex: java.nio.BufferOverflowException
查看>>
Cocos2d-x3.2 EditBox的使用
查看>>