【问题标题】:nullPointer when findViewById() in SimpleCursorAdapter在 SimpleCursorAdapter 中 findViewById() 时的 nullPointer
【发布时间】:2011-03-14 20:19:12
【问题描述】:

我使用 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),所以我认为在这个扩展类中我仍然做错了。

【问题讨论】:

  • 除了 ClassCastException,如果您的光标只返回一个条目,这段代码是否有效?
  • @Quintin 我无法检查这一点,我恢复到旧版本,并尝试使用以下建议的新版本。你知道为什么在这种情况下会抛出 ClassCastException 吗?单击现在工作(颜色已更改)列表中的条目后,它应该打开一个新活动 - 我现在在这个(常规活动,没有列表)中得到了一个 ClassCastException,而我以前没有。
  • *没有尝试过Project > Clean,所以我会在我开始工作时尝试一下;在 SO 上搜索显示生成的 R 文件可能会不同步导致此问题。
  • Project > Clean 解决了 ClassClassExceptions :)

标签: android android-layout listactivity simplecursoradapter


【解决方案1】:

convertView 永远是一个现有的实例是不正确的;你应该检查它是否为空,然后实例化它。如果没有,您可以像以前一样更改它。

应该是这样的:

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

【讨论】:

  • 谢谢 - 我认为这个解决方案等同于适配器通常如何重用不可见的视图? (即已被滚出用户视线)
  • 没错,这就是他们重用视图而不是每次都膨胀并节省处理时间和内存的方式。
【解决方案2】:

我会修改 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;
}

【讨论】:

    【解决方案3】:

    我认为你得到 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。如果使用 ListActivity,则不需要使用 ListView,也不需要在 Activity 中设置内容视图。

    希望对你有帮助!

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-10
        • 2014-05-12
        • 1970-01-01
        相关资源
        最近更新 更多