深入理解ListView (1)— 一天一点源码

来源:互联网 发布:一淘是淘宝的吗 编辑:程序博客网 时间:2024/06/03 18:21

AdapterView - 一天一点源码

前言:ListView结构

由图可知,ListView继承至AbsListView,AbsListView又继承至AdapterView(还实现了TextWatcher方法,往后再说)。
计划从AdapterView开始对ListView进行理解,了解ListView的实现机制。

1、说明

/** * An AdapterView is a view whose children are determined by an {@link Adapter}. */public abstract class AdapterView<T extends Adapter> extends ViewGroup {...}

AdapterView是一个带有一个Adapter子类泛型的抽象类,继承自ViewGroup。

2、方法

public AdapterView(Context context) {    this(context, null);}public AdapterView(Context context, AttributeSet attrs) {    this(context, attrs, 0);}public AdapterView(Context context, AttributeSet attrs, int defStyleAttr) {    this(context, attrs, defStyleAttr, 0);}public AdapterView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {    super(context, attrs, defStyleAttr, defStyleRes);    // If not explicitly specified this view is important for accessibility.    if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {        setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);    }}

AdapterView的5个构造方法。

public interface OnItemClickListener {    void onItemClick(AdapterView<?> parent, View view, int position, long    id);}public void setOnItemClickListener(@Nullable OnItemClickListener listener) {    mOnItemClickListener = listener;}@Nullablepublic final OnItemClickListener getOnItemClickListener() {    return mOnItemClickListener;}

定义了item点击监听接口,实现点击监听的方法,以及获得Item的当前监听器对象的方法

public boolean performItemClick(View view, int position, long id) {    final boolean result;    if (mOnItemClickListener != null) {        playSoundEffect(SoundEffectConstants.CLICK);        mOnItemClickListener.onItemClick(this, view, position, id);        result = true;    } else {        result = false;    }    if (view != null) {        view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);    }    return result;}

如果点击监听被定义,实现点击事务。

    boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id);}public void setOnItemLongClickListener(OnItemLongClickListener listener) {    if (!isLongClickable()) {        setLongClickable(true);    }    mOnItemLongClickListener = listener;}

定义长按点击事件的方法

public interface OnItemSelectedListener {       void onItemSelected(AdapterView<?> parent, View view, int position, long id);    void onNothingSelected(AdapterView<?> parent);}public void setOnItemSelectedListener(@Nullable OnItemSelectedListener listener) {    mOnItemSelectedListener = listener;}@Nullablepublic final OnItemSelectedListener getOnItemSelectedListener() {    return mOnItemSelectedListener;}

定义Item选择监听的接口,Item被选择的监听方法,以及获得当前Item监听器的对象的方法。

@Overridepublic void setOnClickListener(OnClickListener l) {    throw new RuntimeException("Don't call setOnClickListener for an AdapterView. "            + "You probably want setOnItemClickListener instead");}

重写父类方法,设置当前AdapterView的监听。

@Overridepublic void addView(View child) {    throw new UnsupportedOperationException("addView(View) is not supported in AdapterView");}@Overridepublic void addView(View child, int index) {    throw new UnsupportedOperationException("addView(View, int) is not supported in AdapterView");}@Overridepublic void addView(View child, LayoutParams params) {    throw new UnsupportedOperationException("addView(View, LayoutParams) "            + "is not supported in AdapterView");}@Overridepublic void addView(View child, int index, LayoutParams params) {    throw new UnsupportedOperationException("addView(View, int, LayoutParams) "            + "is not supported in AdapterView");}

addView继承自ViewGroup,不支持调用,调用是抛出异常。

@Overridepublic CharSequence getAccessibilityClassName() {    return AdapterView.class.getName();}

返回AdapterView的类名。

public abstract T getAdapter();

返回AdapterView的适配器adapter。

public abstract void setAdapter(T adapter);

设置AdapterView的适配器adapter。

@Overridepublic void removeView(View child) {    throw new UnsupportedOperationException("removeView(View) is not supported in AdapterView");}@Overridepublic void removeViewAt(int index) {    throw new UnsupportedOperationException("removeViewAt(int) is not supported in AdapterView");}@Overridepublic void removeAllViews() {    throw new UnsupportedOperationException("removeAllViews() is not supported in AdapterView");}

重写的ViewGroup的remove方法,依次为移除指定视图,移除指定位置的视图,移除所有视图等。不可被调用,调用抛出异常。

@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {    mLayoutHeight = getHeight();}

重写的ViewGroup的方法,获得当前高度。

public long getSelectedItemId() {    return mNextSelectedRowId;}

获得选中子控件的Id。

public abstract View getSelectedView();

获得选中的视图。

public Object getSelectedItem() {    T adapter = getAdapter();    int selection = getSelectedItemPosition();    if (adapter != null && adapter.getCount() > 0 && selection >= 0) {        return adapter.getItem(selection);    } else {        return null;    }}

获得被选中的Item的对象。

public int getCount() {    return mItemCount;}

获得Item的数量。

public int getPositionForView(View view) {    View listItem = view;    try {        View v;        while ((v = (View) listItem.getParent()) != null && !v.equals(this)) {            listItem = v;        }    } catch (ClassCastException e) {        // We made it up to the window without find this list view        return INVALID_POSITION;    }    if (listItem != null) {        // Search the children for the list item        final int childCount = getChildCount();        for (int i = 0; i < childCount; i++) {            if (getChildAt(i).equals(listItem)) {                return mFirstPosition + i;            }        }    }    // Child not found!    return INVALID_POSITION;}

传入一个视图,返回传入视图的位置。

public int getFirstVisiblePosition() {    return mFirstPosition;}

返回适配器设置的屏幕上可显示第一个Item的位置。

public int getLastVisiblePosition() {    return mFirstPosition + getChildCount() - 1;}

返回适配器设置的屏幕上可显示的最后一个Item的位置。

public abstract void setSelection(int position);

设置当前选择条目。

public void setEmptyView(View emptyView) {    mEmptyView = emptyView;    // If not explicitly specified this view is important for accessibility.    if (emptyView != null            && emptyView.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {        emptyView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);    }    final T adapter = getAdapter();    final boolean empty = ((adapter == null) || adapter.isEmpty());    updateEmptyStatus(empty);}

设置空视图。

public View getEmptyView() {    return mEmptyView;}

获得当前AdapterView的空视图对象。

private void updateEmptyStatus(boolean empty) {    if (isInFilterMode()) {        empty = false;    }    if (empty) {        if (mEmptyView != null) {            mEmptyView.setVisibility(View.VISIBLE);            setVisibility(View.GONE);        } else {            // If the caller just removed our empty view, make sure the list view is visible            setVisibility(View.VISIBLE);        }        // We are now GONE, so pending layouts will not be dispatched.        // Force one here to make sure that the state of the list matches        // the state of the adapter.        if (mDataChanged) {                       this.onLayout(false, mLeft, mTop, mRight, mBottom);         }    } else {        if (mEmptyView != null) mEmptyView.setVisibility(View.GONE);        setVisibility(View.VISIBLE);    }}

设置空视图的可见状态。

public Object getItemAtPosition(int position) {    T adapter = getAdapter();    return (adapter == null || position < 0) ? null : adapter.getItem(position);}传入一个Item位置,获得Adapter中Item对应的数据public long getItemIdAtPosition(int position) {    T adapter = getAdapter();    return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position);}

传入Item的位置,获得Adapter中Item对应的位置

class AdapterDataSetObserver extends DataSetObserver {    private Parcelable mInstanceState = null;    @Override    public void onChanged() {        mDataChanged = true;        mOldItemCount = mItemCount;        mItemCount = getAdapter().getCount();        // Detect the case where a cursor that was previously invalidated has        // been repopulated with new data.        if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null                && mOldItemCount == 0 && mItemCount > 0) {            AdapterView.this.onRestoreInstanceState(mInstanceState);            mInstanceState = null;        } else {            rememberSyncState();        }        checkFocus();        requestLayout();    }    @Override    public void onInvalidated() {        mDataChanged = true;        if (AdapterView.this.getAdapter().hasStableIds()) {            // Remember the current state for the case where our hosting activity is being            // stopped and later restarted            mInstanceState = AdapterView.this.onSaveInstanceState();        }        // Data is invalid so we should reset our state        mOldItemCount = mItemCount;        mItemCount = 0;        mSelectedPosition = INVALID_POSITI结结结结结结N;        mSelectedRowId = INVALID_ROW_ID;        mNextSelectedPosition = INVALID_POSITION;      mNextSelectedRowId = INVALID_ROW_ID;        mNeedSync = false;        checkFocus();        requestLayout();    }    public void clearSavedState() {        mInstanceState = null;    }}

定义内部类,为AdapterView设置观察者,通过重写的onChange,onInvalidated,clearSavedState,对Adapter的状态及参数进行观察,实时做出相应改变。

总结

以上并不是AdapterView的全部源码,只是将我觉得重要的源码,以及一些在ListView中有体现的源码进行了阅读。
粗略感觉AdapterView已实现了Listview的大部分基础功能。
AdapterView中定义了设置ListView中item监听的各种方法,以及设置Adapter,内部内继承观察者类,对数据进行监控…等等。
一点一点的理解,逐步了解ListView的实现机制。

0 0
原创粉丝点击