日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

發布時間:2025/3/8 编程问答 78 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

導師安排我做一個小項目,其中涉及到利用Adapter作為ListView的適配器,為ListView提供數據。選中某一項后,要讓這一項變成選中狀態,也就是背景圖片要換一下。下面我就用一個小例子來模擬。重點不在于實現,而是了解Adapter中notifyDataSetChanged()背后的運行機制。

? ? 我們先做一個小Demo(文中涉及的Demo在文章末尾),功能是選中某一項后,背景顏色會變紅。代碼非常簡單,這里就不解釋了。值得注意的是,當我們需要ListView進行刷新的時候,我們需要調用Adapter.notifyDataSetChanged()來讓界面刷新。

1 public class MainActivity extends Activity { 2 @Override 3 protected void onCreate(Bundle savedInstanceState) { 4 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 8 ListView main_list = (ListView)this.findViewById(R.id.main_list); 9 MyArrayAdapter mArrayList=new MyArrayAdapter(this,R.layout.list_item,getData()); 10 main_list.setAdapter(mArrayList); 11 main_list.setOnItemClickListener(mArrayList); 12 } 13 14 private String[] getData() { 15 return new String[]{"測試數據1","測試數據2","測試數據3","測試數據4"}; 16 } 17 }

適配器MyArrayAdapter代碼:

1 public class MyArrayAdapter extends ArrayAdapter<String> implements 2 OnItemClickListener { 3 4 private int itemClicked; 5 6 public MyArrayAdapter(Context context, int textViewResourceId, 7 String[] objects) { 8 super(context, textViewResourceId, objects); 9 10 } 11 @Override 12 public View getView(int position, View convertView, ViewGroup parent) { 13 14 convertView=super.getView(position, convertView, parent); 15 //如果是被點擊的項,變換顏色 16 if (position==this.itemClicked) { 17 convertView.setBackgroundColor(Color.RED); 18 }else { 19 convertView.setBackgroundColor(Color.WHITE); 20 } 21 return convertView; 22 } 23 @Override 24 public void onItemClick(AdapterView<?> parent, View view, int position, 25 long id) { 26 //設置某項被點擊 27 itemClicked=position; 28 this.notifyDataSetChanged(); 29 } 30 31 }

?

下面就讓我們跟進去MyArrayAdapter.notifyDataSetChange()中看看。在本文中,我所查看的Android源代碼是4.4.0的,不同版本可能有所出入。

1 public void notifyDataSetChanged() { 2 super.notifyDataSetChanged(); 3 mNotifyOnChange = true; 4 }

源代碼就簡單兩句話,那么繼續看看super是什么?

public class ArrayAdapter<T> extends BaseAdapter implements Filterable

從類的聲明中,父類就是ArrayAdapter,而ArrayList的父類是BaseAdapter。我們跟進BaseAdapter中看看。

1 public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { 2 private final DataSetObservable mDataSetObservable = new DataSetObservable(); 3 //...省略不必要的代碼 4 public void registerDataSetObserver(DataSetObserver observer) { 5 mDataSetObservable.registerObserver(observer); 6 } 7 8 public void unregisterDataSetObserver(DataSetObserver observer) { 9 mDataSetObservable.unregisterObserver(observer); 10 } 11 12 public void notifyDataSetChanged() { 13 mDataSetObservable.notifyChanged(); 14 } 15 16 public void notifyDataSetInvalidated() { 17 mDataSetObservable.notifyInvalidated(); 18 } 19 //...省略不必要的代碼 20 }

我們發現其實就是DataSetObservable這個對象在發生作用,但是DataSetObservable這個對象估計就是一個簡單的觀察者的實現,Android框架的編寫者不大可能將業務邏輯放在這里面,不過我們還是要確認是不是跟我們所想的一樣。

1 public class DataSetObservable extends Observable<DataSetObserver> { 2 /** 3 * Invokes onChanged on each observer. Called when the data set being observed has 4 * changed, and which when read contains the new state of the data. 5 */ 6 public void notifyChanged() { 7 synchronized(mObservers) { 8 for (DataSetObserver observer : mObservers) { 9 observer.onChanged(); 10 } 11 } 12 } 13 14 /** 15 * Invokes onInvalidated on each observer. Called when the data set being monitored 16 * has changed such that it is no longer valid. 17 */ 18 public void notifyInvalidated() { 19 synchronized (mObservers) { 20 for (DataSetObserver observer : mObservers) { 21 observer.onInvalidated(); 22 } 23 } 24 } 25 }

果然,跟預想的一樣,它只是簡單地調用了綁定在它身上的回調接口。那么BaseAdapter.notifyDataSetChange()的接口具體是在哪里綁定的呢?很有可能在構造函數中綁定,我們跟進ArrayListAdapter看看。

1 public ArrayAdapter(Context context, int textViewResourceId, List<T> objects) { 2 init(context, textViewResourceId, 0, objects); 3 } 4 5 private void init(Context context, int resource, int textViewResourceId, List<T> objects) { 6 mContext = context; 7 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 8 mResource = mDropDownResource = resource; 9 mObjects = objects; 10 mFieldId = textViewResourceId; 11 }

ArrayListAdapter中有很多構造函數,但是幾經輾轉全部都會轉到init()函數中,很遺憾,我們撲了。那么還在哪里可能綁定notifyDataSetChange()回調函數呢?其實從MainActivity中Adapter的初始化過程中,基本上只能鎖定在MainActivity第十行中setAdapter函數中。接下去看看 public void setAdapter(ListAdapter adapter)這個函數。?

1 public void setAdapter(ListAdapter adapter) { 2 if (null != mAdapter) { 3 mAdapter.unregisterDataSetObserver(mDataSetObserver); 4 } 5 6 resetList(); 7 mRecycler.clear(); 8 9 if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { 10 mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); 11 } else { 12 mAdapter = adapter; 13 } 14 15 mOldSelectedPosition = INVALID_POSITION; 16 mOldSelectedRowId = INVALID_ROW_ID; 17 if (mAdapter != null) { 18 mAreAllItemsSelectable = mAdapter.areAllItemsEnabled(); 19 mOldItemCount = mItemCount; 20 mItemCount = mAdapter.getCount(); 21 checkFocus(); 22 23 mDataSetObserver = new AdapterDataSetObserver(); 24 mAdapter.registerDataSetObserver(mDataSetObserver); 25 26 mRecycler.setViewTypeCount(mAdapter.getViewTypeCount()); 27 28 int position; 29 if (mStackFromBottom) { 30 position = lookForSelectablePosition(mItemCount - 1, false); 31 } else { 32 position = lookForSelectablePosition(0, true); 33 } 34 setSelectedPositionInt(position); 35 setNextSelectedPositionInt(position); 36 37 if (mItemCount == 0) { 38 // Nothing selected 39 checkSelectionChanged(); 40 } 41 42 if (mChoiceMode != CHOICE_MODE_NONE && 43 mAdapter.hasStableIds() && 44 mCheckedIdStates == null) { 45 mCheckedIdStates = new LongSparseArray<Boolean>(); 46 } 47 48 } else { 49 mAreAllItemsSelectable = true; 50 checkFocus(); 51 // Nothing selected 52 checkSelectionChanged(); 53 } 54 55 if (mCheckStates != null) { 56 mCheckStates.clear(); 57 } 58 59 if (mCheckedIdStates != null) { 60 mCheckedIdStates.clear(); 61 } 62 63 requestLayout(); 64 }

setAdapter(...)這個函數有點長,不過我們只需要關注跟notifiDataSetChange()有關的實現,也就是第23、24行。不過這里另一個值得關注的點就是第63行,requestLayout()這個函數,它主要就是用來刷新界面,讓界面重新繪制的。在23,、24行,綁定了一個AdapterDataSetObserver對象,下面我們就跟進去看看。從前面DataSetObservable的實現中,我們知道了它在notifyDataSetChange()的時候會調用DataSetObserver的onChange()。

1 class AdapterDataSetObserver extends DataSetObserver 2 { 3 private Parcelable mInstanceState = null; 4 5 AdapterDataSetObserver() { 6 } 7 public void onChanged() { mDataChanged = true; 8 mOldItemCount = mItemCount; 9 mItemCount = getAdapter().getCount(); 10 11 if ((getAdapter().hasStableIds()) && (mInstanceState != null) && (mOldItemCount == 0) && (mItemCount > 0)) 12 { 13 onRestoreInstanceState(mInstanceState); 14 mInstanceState = null; 15 } else { 16 rememberSyncState(); 17 } 18 checkFocus(); 19 requestLayout(); 20 } 21 //...省略不必要代碼 22 }

終于,在第19行,我們看見了requestLayout(),它就是用來重繪界面的,它在ViewRootImpl.java中有具體的實現。

1 public void requestLayout() { 2 checkThread(); 3 mLayoutRequested = true; 4 scheduleTraversals(); 5 }

關于scheduleTraversals()的實現,涉及到Android中View的繪制流程,感興趣的可以看看《Android視圖狀態及重繪流程分析,帶你一步步深入了解View(三)》。

? ? 到了這里,我們就清楚了notifyDataSetChange()背后的實現機制了,在不知不覺之間Android框架幫我們干了很多事情,不過需要提醒的時,每一次notifyDataSetChange()都會引起界面的重繪。當需要修改界面上View的相關屬性的時候,最后先設置完成再調用notifyDataSetChange()來重繪界面。

?本文轉自陳哈哈博客園博客,原文鏈接http://www.cnblogs.com/kissazi2/p/3721941.html如需轉載請自行聯系原作者


kissazi2

總結

以上是生活随笔為你收集整理的从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久香视频 | 国产精品黄在线观看 | 欧美在线观看一区 | 鲁丝一区二区 | 88久久精品无码一区二区毛片 | 亚洲成人一二区 | 久久婷婷综合国产 | 色老板av | 艳母动漫在线播放 | 激情综合网五月天 | 粉嫩av.com| 蜜桃精品噜噜噜成人av | 欧美一区二区三区激情啪啪 | 黄色av网站在线看 | 亚洲欧美一区二区三区在线 | 色污网站 | 肉嫁高柳在线 | 日韩在线一区二区三区四区 | 白白色免费视频 | 日韩电影福利 | 国产一区二区视频在线播放 | 5566在线| 中文精品无码中文字幕无码专区 | 欧美一级片黄色 | 九九小视频| 一级片毛片 | 国产一区二区精品在线 | 理论片大全免费理伦片 | 欧美性猛交xxx乱大交3蜜桃 | 亚洲成人视屏 | wwwxx欧美 | www.com捏胸挤出奶 | 国产无遮挡a片又黄又爽 | 日本www在线播放 | 亚洲综合久久av | 99成人国产精品视频 | 嫩草视频在线播放 | 天天摸天天摸 | 大肉大捧一进一出好爽视频 | 免费无码毛片一区二区app | 侵犯女教师一区二区三区 | 香蕉av网 | 香港a毛片 | 色偷偷网站 | 亚洲天天在线 | 国产精品99| 国产性猛交xxxⅹ交酡全过程 | 日韩av综合| 国产情侣91| 日p免费视频| 欧洲-级毛片内射 | 天天撸在线视频 | 激情九月婷婷 | www.插插插 | 中国一级黄色大片 | 欧美一区二区三区免 | 国产玖玖视频 | 欧美十大老熟艳星 | 欧美精品一区二区蜜臀亚洲 | 性综合网 | 91福利在线导航 | 一区二区免费看 | 一区视频在线播放 | 欧美精品免费在线 | 亚洲精品成人 | 91av免费看 | 亚洲欧洲精品在线 | 天堂а√在线中文在线新版 | 国产男人的天堂 | 欧美日韩精品一区二区在线播放 | 亚洲国产精品综合久久久 | 最近的中文字幕在线看视频 | 蜜桃av在线免费观看 | 96视频在线观看 | 成人欧美激情 | 国产区视频在线 | 国产一级免费 | 男人日女人网站 | 小草av在线 | 男女啪啪无遮挡 | 国产精品久久久久久久久久久久久久久久 | 色综合天天综合网天天狠天天 | 色哟哟一区二区 | 在线免费观看污网站 | 欧美亚一区二区三区 | 91看片淫黄大片 | 国产欧美激情在线观看 | 久久久亚洲国产 | 免费三片60分钟 | 精品国产乱码久久久久久久 | 亚洲社区在线 | 桃色av网站| 午夜操一操 | 97影院在线午夜 | 国产日韩欧美精品一区 | 国产传媒中文字幕 | 亚洲高清免费观看 | 天天操天天摸天天干 | 阿v天堂2017 欧美小视频在线观看 |