1. adapter.notifyDataSetChange ()
此方法是BaseAdapter下面的方法:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public boolean hasStableIds() {
return false;
}
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* Notifies the attached observers that the underlying data has been changed
* and any View reflecting the data set should refresh itself.
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
其中DataSetObservable为:
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* Invokes {@link DataSetObserver#onChanged} on each observer.
* Called when the contents of the data set have changed. The recipient
* will obtain the new contents the next time it queries the data set.
*/
public void notifyChanged() {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
/**
* Invokes {@link DataSetObserver#onInvalidated} on each observer.
* Called when the data set is no longer valid and cannot be queried again,
* such as when the data set has been closed.
*/
public void notifyInvalidated() {
synchronized (mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onInvalidated();
}
}
}
}
而所谓的mObservers变量在父类中:
public abstract class Observable<T> {
/**
* The list of observers. An observer can be in the list at most
* once and will never be null.
*/
protected final ArrayList<T> mObservers = new ArrayList<T>();
/**
* Adds an observer to the list. The observer cannot be null and it must not already
* be registered.
* @param observer the observer to register
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is already registered
*/
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObservers.add(observer);
}
}
/**
* Removes a previously registered observer. The observer must not be null and it
* must already have been registered.
* @param observer the observer to unregister
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is not yet registered
*/
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
/**
* Remove all registered observers.
*/
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
还差一个什么类呢,DataSetObserver类,此类 上述类中的ArrayList中的数据类型(即观察者接口)
public abstract class DataSetObserver {
/**
* This method is called when the entire data set has changed,
* most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
*/
public void onChanged() {
// Do nothing
}
/**
* This method is called when the entire data becomes invalid,
* most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
* {@link Cursor}.
*/
public void onInvalidated() {
// Do nothing
}
}
相关的代码都贴的差不多了,来梳理一下流程:
额,看了一下源码,流程貌似没什么需要梳理的,就是一个观察者模式。ListView为观察者,其应该是实现了DataSetObserver类,然后保存在List中,当调用notifyDataSetChange()时,即使通知所有的观察者数据变化,最后调用onChange()方法,而此方法有子类实现。
那个这个观察者是什么时候注册的呢?
来到ListView源码中,ListView继承AbsListView,来看看AbsListView中的onAttachedToWindow方法:
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
final ViewTreeObserver treeObserver = getViewTreeObserver();
treeObserver.addOnTouchModeChangeListener(this);
if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) {
treeObserver.addOnGlobalLayoutListener(this);
}
if (mAdapter != null && mDataSetObserver == null) {
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
// Data may have changed while we were detached. Refresh.
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
}
}
因为之前会setAdapter,所以会进入到if语句块中,我们来看看AdapterDataSetObserver类:
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
@Override
public void onInvalidated() {
super.onInvalidated();
if (mFastScroll != null) {
mFastScroll.onSectionsChanged();
}
}
}
此类最终实现的是DataSetObserver类,及观察者接口。
然后在onAttachedToWindow()中调用了BaseAdapter的register****了,即向观察者列表List中添加此观察者。
2. 来看看ListView的工作原理
为什么要有Adapter呢?因为ListView的item视图是不确定了,数据也是不确定的,使用Adapter把变化的部分隔离开,ListView就可以专注的做自己的工作(即适配器模式)
下面来了解一下ListView的绘图原理:
a:在AbsListView的onAttachedToWindow()方法中获取Adapter中的Item数量
b:然后调用onLayout方法绘制,onLayout方法会调用子类(即ListView)的layoutChildren方法。
c:layoutChildren方法根据布局模式调用不同的方法,但调用的方法里面都有makeAndAddView方法
d:makeAndAddView方法会先从缓存(RecycleBin)中回去View,获取不到则调用AbsListView中的obtainView方法
e:obtainView方法会调用Adapter的getView方法返回一个视图
还有一点就是,在obtainView调用getView之前,会调用Adapter.getItemViewType获取视图类别
3.RecycleView
RecycleView没有getView方法,取而代之的是onCreateViewHolder和onBindViewHolder。onCreateViewHolder获取ViewHolde对象,viewHolder里面包含item view的引用。获取到ViewHolder之后通过onBindViewHolder来绑定数据。
RecycleView可以通过LayoutManager来设置布局方式(ListView是通过layoutChildren()来设置的),讲布局的工作交给了LayoutManager。
RecycleView缓存的对象是ViewHolder(listView缓存的是View)。
RecycleView目前没有itemClick事件。