Android-ViewPager+Fragment資料更新問題

來源:互聯網
上載者:User

標籤:代碼   position   mda   called   array   bst   map   eof   arraylist   

由於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;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {            tagList.add(makeFragmentName(container.getId(), getItemId(position))); //把tag存起來           return super.instantiateItem(container, position);        } @Overridepublic void destroyItem(ViewGroup container, int position, Object object){super.destroyItem(container, position, object);tagList.remove(makeFragmentName(container.getId(), getItemId(position)));//把tag刪掉}@Overridepublic Fragment getItem(int position) {String url = mDatas.get(position);WebViewFragmentV4 webview = new WebViewFragmentV4(url);//本文測試的Fragment是一個WebViewFragment
return webview;}@Overridepublic 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. */@Overridepublic 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. */@Overridepublic void onPause() {super.onPause();mWebView.onPause();}/** * Called when the fragment is no longer resumed. Pauses the WebView. */@Overridepublic 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. */@Overridepublic void onDestroyView() {mIsWebViewAvailable = false;super.onDestroyView();}/** * Called when the fragment is no longer in use. Destroys the internal state * of the WebView. */@Overridepublic 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 {@Overridepublic boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon);}@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);}@Overridepublic 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() {@Overridepublic 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;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {            tagList.add(makeFragmentName(container.getId(), getItemId(position)));            return super.instantiateItem(container, position);        } @Overridepublic 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;}@Overridepublic Fragment getItem(int position) {String url = mDatas.get(position);WebViewFragmentV4 webview = new WebViewFragmentV4(url);return webview;}@Overridepublic 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資料更新問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.