由於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內容的作用。
}
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!
