SimpleCursorAdapter中的findViewById()时的nullPointer

时间:2011-03-14 20:19:12

标签: android android-layout listactivity simplecursoradapter

我正在使用SimpleCursorAdapter和一个xml文件,其中定义了一些视图:

<LinearLayout ...>
    <ImageView android:id="@+id/listIcon" />
    <TextView android:id="@+id/listText" />
</LinearLayout>

我的目标是以编程方式设置TextView的文本颜色,以及LinearLayout的背景颜色(即ListView中的每一行);颜色从数据库返回。

在尝试操作TextView时,我得到了NPE,例如,在发现它之后没有抱怨:

TextView tv = (TextView) findViewById(R.id.listText);
tv.setTextColor(color); // NPE on this line

哪个是公平的;如果列表中有多个条目,则可以合理地假设“ R.id.listText ”不起作用。所以我扩展了SimpleCursor Adapter:

public View getView(int position, View convertView, ViewGroup parent) {
    View row = super.getView(position, convertView, parent);
    TextView text = (TextView) row.findViewById(R.id.listText);
    // ImageView icon = (ImageView) row.findViewById(R.id.listIcon);

    // If there's an icon defined
    if (mIcon_id != 0) {
        // icon.setImageResource(mIcon_id);
    }

    // If text color defined
    if (mTextColor != 0) {
        text.setTextColor(mTextColor);
    }

    // If background color set
    if (mBackgroundColor != 0) {
        row.setBackgroundColor(mBackgroundColor);
    }
    return(row);
}

我得到两个不同的错误:

  • 类似的NPE被抛出 “ text.setTextColor(mTextColor)
  • 如果带有ImageView的行是 没有评论,我得到了 “ ClassCastException异常: android.widget.TextView “我在哪里 调用 “ row.findViewById(R.id.listIcon)

作为参考,我试图使用Commonsware的示例代码,将其应用于我的情况。 link (pdf)


改为:

public View getView(int position, View convertView, ViewGroup parent) {
    convertView = super.getView(position, convertView, parent);

    if (convertView == null) convertView = View.inflate(mContext, R.layout.theme_item, null);
    TextView text = (TextView) convertView.findViewById(R.id.listText_tv);
    ImageView icon = (ImageView) convertView.findViewById(R.id.listIcon_iv);

    // If there's an icon defined
    if (mIcon_id != 0) {
        icon.setImageResource(mIcon_id);
    }

    // If text color defined
    if (mTextColor != 0) {
        text.setTextColor(mTextColor);
    }

    // If background color set
    if (mBackgroundColor != 0) {
        convertView.setBackgroundColor(mBackgroundColor);
    }
    bindView(convertView, mContext, mCursor);
    return(convertView);
}

现在我在下一个活动中得到一个ClassCastException(在列表项目上单击)。在下一个活动中没有修改任何内容;当使用SimpleListAdapter作为具有条目的列表(点击将导致Activity2)时,它工作,所以我认为这仍然是我在这个扩展类中做错了。

4 个答案:

答案 0 :(得分:5)

convertView 并不总是现有的实例;你应该检查它是否为null然后实例化它。如果没有,您可以像改变它一样进行更改。

这应该是:

public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView == null)
        convertView = //inflate your row here
    View row = convertView;
    //Manipulate the row here
    return(row);
}

答案 1 :(得分:1)

我会修改getView方法:

public View getView(int position, View convertView, ViewGroup parent) {
    convertView = View.inflate(getContext(), R.layout.myLayout, null);
    TextView text = (TextView) convertView.findViewById(R.id.listText);
    ImageView icon = (ImageView) convertView.findViewById(R.id.listIcon);

    // If there's an icon defined
    if (mIcon_id != 0) {
      icon.setImageResource(mIcon_id);
    }

    // If text color defined
    if (mTextColor != 0) {
      text.setTextColor(mTextColor);
    }

    // If background color set
    if (mBackgroundColor != 0) {
      convertView.setBackgroundColor(mBackgroundColor);
    }

    return convertView;
}

答案 2 :(得分:0)

我认为你正在获得NPE,因为你试图在不存在的视图中创建textview和imageview。

如果要使用数据库中的条目对ListView进行充气,可以在活动中使用ListView定义main.xml:

<LinearLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:id="@+id/listView1">
</ListView>

并在onCreate方法中,您使用setContentView(R.layout.main);将视图设置为此xml。然后,将光标创建到数据库和自定义适配器:

    MySimpleCursorAdapter adapter = new MySimpleCursorAdapter(this, R.layout.entry,
                names, new String[] {Phones.NAME, Phones.NUMBER}, new int[] {
                R.id.listIcon, R.id.listText});
    startManagingCursor(cursor);
    ListView listView = (ListView) findViewById(R.id.listView1);
    listView.setAdapter(adapter);

并使用listIcon和listText定义一个entry.xml,其中适配器指向。在我的例子中,我正在查询联系人列表中的姓名和号码。

在自定义适配器中,您应该在getView或bindView中访问textview和imageview而没有任何问题。

Here您有一个示例来获取联系人列表中的所有联系人及其图片,名称和编号,但使用ListActivity而不是活动,只有一个xml有两个文本视图和一个imageview。如果使用ListActivity,则无需使用ListView,也无需在活动中设置内容视图。

我希望它有所帮助!

答案 3 :(得分:-2)

不要忘记为每个视图添加:layout_width和layout_heigth。