ListView与Adapter部分源码解析

本文解析了Android中Adapter的工作原理,包括BaseAdapter的notifyDataSetChanged方法如何通过观察者模式更新UI,以及ListView与RecyclerView的区别。深入探讨了RecyclerView的ViewHolder模式及其优势。
摘要由CSDN通过智能技术生成

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事件。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值