码迷,mamicode.com
首页 > 其他好文 > 详细

ListActivity和ListView源码分析(1) 加载布局

时间:2015-02-09 12:56:07      阅读:139      评论:0      收藏:0      [点我收藏+]

标签:

最近写代码总是用到ListActivity,因此看了下ListView和ListActivity的源代码.

1 加载布局

一般来说我们使用自定义的ListActivity时,在创建时首先需要调用setContentView函数来设置这个Activity对应的view布局.

而从Activity.onContentChanged()的api文档说明来看,setContentView方法会导致onContentChanged方法被调用.因此我们接下来来看下ListActivity的onContentChanged方法.

    public void onContentChanged() {
        super.onContentChanged();
        View emptyView = findViewById(com.android.internal.R.id.empty);
        mList = (ListView)findViewById(com.android.internal.R.id.list);
        if (mList == null) {
            throw new RuntimeException(
                    "Your content must have a ListView whose id attribute is " +
                    "‘android.R.id.list‘");
        }
        if (emptyView != null) {
            mList.setEmptyView(emptyView);
        }
        mList.setOnItemClickListener(mOnClickListener);
        if (mFinishedStart) {
            setListAdapter(mAdapter);
        }
        mHandler.post(mRequestFocus);
        mFinishedStart = true;
    }

1.1 R.id.list 获取ListView

我们可以看到这里取了两个固定ID的view,一个是R.id.empty,一个是R.id.list.
R.id.list对应Activity中的listview,这也是为什么官方文档(参看前一篇文档)中写道”确保你自定义的Layout包含一个id为”@android:id/list”的ListView”.我们也可以看到如果系统取不到R.id.list对应的view,会直接抛出异常.得到的这个view将保存在mList中.

1.2 R.id.empty 获取空视图

而R.id.empty在官方文档中也有提到,这view将会在list view为空时显示.
因为mList刚刚获取得到,因此此时肯定为空,一旦我们得到这个empty view,立刻调用ListView的setEmptyView函数:

    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);
    }

这个时候adapter尚未设置所以肯定为空,所以empty为true.
updateEmptyStatus主要是设置一些可见性之类的参数.

1.3 setOnItemClickListener注册点击回调

接下来onContentChanged函数调用了ListView的setOnItemClickListener方法注册每个item的点击回调监听类mOnClickListener.

    private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
        public void onItemClick(AdapterView<?> parent, View v, int position, long id)
        {
            onListItemClick((ListView)parent, v, position, id);
        }
    };

我们看到这里调用了方法onListItemClick,这也就是为什么我们希望在自定义的ListActivity中监听每个item的点击方法时,必须重载父类中的onListItemClick方法.

1.4 mFinishedStart

回到ListActivity的onContentChanged函数中来,mFinishedStart参数起到了这样一个作用.
当这个Activity被最初创建时,mFinishedStart值为false.因此这个时候自然也不需要设置adapter.而在onContentChanged函数被调用过一次之后, mFinishedStart变为true.这保证了在后面已经设置了adapter之后,一旦内容变化,adapter不需要再次被用户手动设置.

最后mHandler.post(mRequestFocus);通知父类mList可以获得焦点.至此,setContentView方法结束.

2 setListAdapter设置adapter

后面我们使用ListActivity一般就会调用方法setListAdapter,设置对应的adapter用于给ListView提供数据.这个函数涉及到了ListView和Adapter交互的过程,我们将在下一章节详细讲述.

  public void setAdapter(ListAdapter adapter) {
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }
        resetList();
        mRecycler.clear();

        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
        } else {
            mAdapter = adapter;
        }

        mOldSelectedPosition = INVALID_POSITION;
        mOldSelectedRowId = INVALID_ROW_ID;

        // AbsListView#setAdapter will update choice mode states.
        super.setAdapter(adapter);

        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
            checkFocus();

            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);

            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());

            int position;
            if (mStackFromBottom) {
                position = lookForSelectablePosition(mItemCount - 1, false);
            } else {
                position = lookForSelectablePosition(0, true);
            }
            setSelectedPositionInt(position);
            setNextSelectedPositionInt(position);

            if (mItemCount == 0) {
                // Nothing selected
                checkSelectionChanged();
            }
        } else {
            mAreAllItemsSelectable = true;
            checkFocus();
            // Nothing selected
            checkSelectionChanged();
        }

        requestLayout();
    }

ListActivity和ListView源码分析(1) 加载布局

标签:

原文地址:http://blog.csdn.net/lee_3do/article/details/43668757

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!