日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 【Android】從源碼分析PagerAdapter/FragmentPagerAdapter調用notifydataSetChanged()刷新的原理

【Android】從源碼分析PagerAdapter/FragmentPagerAdapter調用notifydataSetChanged()刷新的原理

來源:程序員人生   發布時間:2015-05-13 08:19:58 閱讀次數:5646次

相信譽過viewpager的同學都會遇到調用notifydataSetChanged()后不刷新或不符合預期的問題,今天就來分析分析這里的來龍去脈。這1切還得從viewpager的setAdapter說起:

/** * Set a PagerAdapter that will supply views for this pager as needed. * * @param adapter Adapter to use */ public void setAdapter(PagerAdapter adapter) { ...(省略若干行,下同) ... final PagerAdapter oldAdapter = mAdapter; mAdapter = adapter; mExpectedAdapterCount = 0; if (mAdapter != null) { if (mObserver == null) { mObserver = new PagerObserver(); } mAdapter.registerDataSetObserver(mObserver); ... ... } ... }

mAdapter.registerDataSetObserver(mObserver)這里用到了視察者模式,mObserver是PagerObserver的1個實例,而PagerObserver是ViewPager的1個內部類,其聲明以下:

private class PagerObserver extends DataSetObserver { @Override public void onChanged() { //這里調用了viewpager的dataSetChanged()方法,下同 dataSetChanged(); } @Override public void onInvalidated() { dataSetChanged(); } }

所以當mAdapter數據有變化調用notifydatasetchanged()刷新時就會調用到PagerObserver 的onChanged方法,繼而調用到了viewpager的dataSetChanged()方法:

void dataSetChanged() { // This method only gets called if our observer is attached, so mAdapter is non-null. final int adapterCount = mAdapter.getCount(); mExpectedAdapterCount = adapterCount; boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 && mItems.size() < adapterCount; int newCurrItem = mCurItem; boolean isUpdating = false; for (int i = 0; i < mItems.size(); i++) { final ItemInfo ii = mItems.get(i); final int newPos = mAdapter.getItemPosition(ii.object); if (newPos == PagerAdapter.POSITION_UNCHANGED) { continue; } if (newPos == PagerAdapter.POSITION_NONE) { mItems.remove(i); i--; if (!isUpdating) { mAdapter.startUpdate(this); isUpdating = true; } mAdapter.destroyItem(this, ii.position, ii.object); needPopulate = true; ... } ... ... } ... if (needPopulate) { ... ... setCurrentItemInternal(newCurrItem, false, true); requestLayout(); } }

這里看到,調用mAdapter.getItemPosition,如果返回的值是POSITION_UNCHANGED(PagerAdapter的默許實現),則needPopulate為false,就不會調用到setCurrentItemInternal(里面間接調用到instantiateItem(),后面講到),所以就不會刷新視圖。反之,如果返回值是POSITION_NONE,則needPopulate為true,就會調用到setCurrentItemInternal:

void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) { ... populate(item); ... }

而populate(item)里面會調用到addNewItem:

ItemInfo addNewItem(int position, int index) { ItemInfo ii = new ItemInfo(); ii.position = position; ii.object = mAdapter.instantiateItem(this, position); ii.widthFactor = mAdapter.getPageWidth(position); if (index < 0 || index >= mItems.size()) { mItems.add(ii); } else { mItems.add(index, ii); } return ii; }


這里看到調用到了mAdapter.instantiateItem(this, position);而PagerAdapter的instantiateItem里甚么都沒做。

所以如果我們用的是PagerAdapter,我們需要復寫instantiateitem,例如我們可以這么寫:

@Override public Object instantiateItem(ViewGroup view, int position) { view.addView(mList.get(position)); return mList.get(position); }

而對FragmentPagerAdapter,它復寫了instantiateitem:

@Override public Object instantiateItem(ViewGroup container, int position) { if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } final long itemId = getItemId(position); // Do we already have this fragment? String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name); if (fragment != null) { if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment); mCurTransaction.attach(fragment); } else { fragment = getItem(position); if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment); mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), itemId)); } if (fragment != mCurrentPrimaryItem) { fragment.setMenuVisibility(false); fragment.setUserVisibleHint(false); } return fragment; }

其中,getItemId的默許實現:

public long getItemId(int position) { return position; }
也就是item對應的下標就是item的id。另外makeFragmentName的實現:

private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; }
這里makeFragmentName相當于為這個fragment組裝成1個標識Tag,如果之前沒添加過這個fragment,也就是mFragmentManager.findFragmentByTag(name)返回null,那末就調用 getItem(position);獲得fragment,然后把這個fragment添加進去。

反之,也就是之前已添加過這個fragment了,則不會調用 getItem(position)了,而是直接attach上這個fragment。


參考

http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifydatasetchanged-does-not-work.html









生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 91亚洲成人 | 欧美日韩免费一区二区三区 | 黄色三级视频 | 一区二区在线看 | 精品日韩一区二区三区免费视频 | 亚洲日韩中文字幕一区 | 亚洲福利在线观看 | 99re在线视频 | 亚洲精品高清视频 | 久久成人免费视频 | 91社影院在线观看 | 美女一区二区三区 | 日本三级网址 | 亚洲精品一区二区久 | 免费在线a | 久久久久久中文字幕 | 精品96久久久久久中文字幕无 | 日韩免费激情电影 | 黄色片在线 | 免费国产在线视频 | 久久久久网站 | 国产精品久久久久久久久久久免费看 | 中文在线一区 | 加勒比在线免费视频 | 日韩欧美自拍 | 欧美一区二区三区免费 | 中文字幕日韩在线 | 日韩成人片 | 一级免费视频 | 国产精品美女一区二区三区 | 亚洲麻豆 | 久久久久9999亚洲精品 | 熟女毛片 | 久久久久久久久久国产 | 亚洲在线视频观看 | 在线观看成人av | 色婷婷91 | 亚洲精品一区 | 国产精品99久久久久久似苏梦涵 | 日韩黄色网址 | 蜜臀网|