nullPointer, когда findViewById () в SimpleCursorAdapter - PullRequest
4 голосов
/ 14 марта 2011

Я использовал SimpleCursorAdapter с xml-файлом, в котором определены некоторые представления:

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

Моя цель состояла в том, чтобы программно установить цвет текста TextView и цвет фона LinearLayout (то есть каждой строки в ListView); цвет возвращается из базы данных.

Я получал NPE при попытке манипулировать TextView, например, после того, как он нашел его без жалоб:

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

Что справедливо; если в списке несколько записей, разумно предположить, что « R.id.listText » не будет работать. Поэтому я расширил адаптер SimpleCursor:

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, применяя его к моей ситуации. ссылка (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 ]

5 голосов
/ 14 марта 2011

Это неправда, что 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);
}
1 голос
/ 15 марта 2011

Я бы изменил метод 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;
}
0 голосов
/ 15 марта 2011

Я думаю, что вы получаете NPE, потому что вы пытаетесь создать текстовое представление и изображение в виде, где их нет.

Когда вы хотите наполнить ListView записями из базы данных, в своей деятельности вы определяете main.xml с ListView:

<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 вы устанавливаете представление для этого xml с помощью setContentView(R.layout.main);. Затем вы создаете курсор для своей базы данных и свой пользовательский адаптер:

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

и вы определяете entry.xml со своими listIcon и listText, на которые указывает адаптер. В моем примере я запрашиваю имена и номера из списка контактов.

В вашем пользовательском адаптере вы должны без каких-либо проблем получать доступ к вашему текстовому и графическому представлениям внутри getView или bindView.

Здесь у вас есть и пример, чтобы получить все контакты в вашем списке контактов с его изображением, именем и номером, но используя ListActivity вместо активности, и только один xml с двумя текстовыми представлениями и просмотром изображения. Если вы используете ListActivity, вам не нужно использовать ListView, и вам не нужно настраивать представление содержимого в действии.

Надеюсь, это поможет!

0 голосов
/ 14 марта 2011

Не забудьте поставить: layout_width и layout_heigth для каждого из ваших просмотров.

...