Android-ViewPager+Fragment数据更新问题
Posted zhchoutai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android-ViewPager+Fragment数据更新问题相关的知识,希望对你有一定的参考价值。
由于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内容的作用。WebViewFragmentV4.java:} 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; } }
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数据更新问题的主要内容,如果未能解决你的问题,请参考以下文章
安卓开发之Activity传输数据到Fragmen+实例分析
gitee查询用户名和密码 Android Studio 3.5以上版本新特性 sharePreferences 使用 不同的Activity间的preferences共享问题 Fragmen