Android编程学习笔记 之 ListActivity源码详解

前言

最近在研究PreferenceActivity发现是继承自ListActivity的,打开看了下ListActivity的源码,发现也不长,就详细阅读认识一下。

正文

ListActivity简单到只要在onCreate()中调用setListAdapter()方法就可以实现了。
支持空数据显示。

点进去我们看到前两个field很熟悉,就是一个ListView+Adapter
很容易就知道这两个field就是ListActivity的核心,数据存储在Adapter中,展示在ListView中。

    protected ListAdapter mAdapter;
    protected ListView mList;
    /** 省略部分代码 */
    public void setListAdapter(ListAdapter adapter) {
        //加上锁,防止多个线程同时调用这个方法
        synchronized (this) {
            ensureList();//内含setContentView的方法
            mAdapter = adapter;
            mList.setAdapter(adapter);
        }
    }

在调用了setListAdapter()之后,对Adapter重新赋值,并重新设置ListViewAdapter,并且调用了ensureList()方法,重新创建布局。
点进ensureList()方法。

    private void ensureList() {
        if (mList != null) {
            return;
        }
        setContentView(com.android.internal.R.layout.list_content_simple);
    }

哈!原来每次setListAdapter()都会把Adapter替换掉,并且重新setContentView(),怪不得ListActivity不用我们操心布局。
我们再来看看这个布局的内容

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/list"
    android:layout_width="match_parent" 
    android:layout_height="match_parent"
    android:drawSelectorOnTop="false"
    />

也就是说,你可以自己setContentView(),只要你的布局有一个viewIdandroid:id="@android:id/list"的就行。
看到这你可能会无语,就一个简单的ListView就完事了?这么简单我也会啊!
别急,这只是完成了基本的功能而已,还要开放一些接口给子Activity调用。
有了ListView当然要实现各种事件啊。

public void setSelection(int position) {
     mList.setSelection(position);
}
public int getSelectedItemPosition() {
    return mList.getSelectedItemPosition();
}
public long getSelectedItemId() {
    return mList.getSelectedItemId();
}

当然还有点击事件,我们发现有一个点击的监听器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);
    }
};
protected void onListItemClick(ListView l, View v, int position, long id) {
    //空方法,交由子类实现
}

既然有监听器,那又是在哪里设置了这个监听器呢?我们发现有一个onContentChanged()方法。

    public void onContentChanged() {
        super.onContentChanged();  //Activity中是空方法
        View emptyView = findViewById(com.android.internal.R.id.empty); //空数据时显示
        mList = (ListView)findViewById(com.android.internal.R.id.list); //绑定ListView
        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);    //多好啊,recyclerView就没有这个方法
        }
        mList.setOnItemClickListener(mOnClickListener); //设置点击事件
        if (mFinishedStart) {
            // 这个if不知道有什么用意
            setListAdapter(mAdapter);
        }
        mHandler.post(mRequestFocus); //待会解释
        mFinishedStart = true;
    }

可是翻遍源代码也没发现哪里调用了onContentChanged()
从字面上看,onContentChanged()Content改变时的回调接口,等等,Content
我们不是在ensureList()中调用了setContentView()方法吗?
答案是正确的,在调用了setContentView(),会调用onContentChanged()

// Activity的setContentView()调用Window(具体子类是PhoneWindow)的setContentView()方法
// 以下代码出现在PhoneWindow中
@Override  
public void setContentView(int layoutResID) {  
    /** 省略部分代码 */
    mLayoutInflater.inflate(layoutResID, mContentParent);  
    getCallback().onContentChanged();  //注意这里!!!
}

再解释下,上面的mHandler.post(mRequestFocus);

    private Runnable mRequestFocus = new Runnable() {
        public void run() {
            // 用来使ListView获取焦点。
            mList.focusableViewAvailable(mList);
        }
    };
   protected void onDestroy() {
        // Activity销毁时移除
        mHandler.removeCallbacks(mRequestFocus);
        super.onDestroy();
    }

至此,ListActivity已经认识的差不多了。有什么讲错了希望能有大牛来提点一下。
有兴趣的可以自己用recyclerView替换listView实现一个RecyclerActivity.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值