nullPointer, wenn findViewById() in SimpleCursorAdapter
-
24-10-2019 - |
Frage
Ich war mit SimpleCursorAdapter mit einer xml-Datei mit einigen Ansichten definieren:
<LinearLayout ...>
<ImageView android:id="@+id/listIcon" />
<TextView android:id="@+id/listText" />
</LinearLayout>
Mein Ziel war es, legen Sie die text-Farbe der TextView, und die Hintergrundfarbe des LinearLayout (, dass ist, jede Zeile in der ListView) programmgesteuert;die Farbe ist von einer Datenbank zurückgegeben werden.
Ich war immer NPEs, wenn Sie versuchen zu manipulieren, die TextView für Beispiel, nachdem er gefunden hatte, es ohne Beschwerden:
TextView tv = (TextView) findViewById(R.id.listText);
tv.setTextColor(color); // NPE on this line
Das ist fair;wenn es mehrere Einträge in der Liste haben, ist es vernünftig anzunehmen, dass "R. id.listText"wird nicht funktionieren.So erweiterte ich 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);
}
Und ich bekomme zwei verschiedene Fehler:
- Eine ähnliche NPE bespritzt "text.setTextColor(mTextColor)"
- Wenn die Linien mit der Bildansicht sind unkommentiert, bekomme ich einen "Classcastexception-Fehler:android.widget.TextView"wo bin ich aufrufen "Zeile.findViewById(R. id.listIcon)"
Für Referenz, die ich zu verwenden versucht Commonsware Beispielcode, die Anwendung, um meine situation. link (pdf)
Verändert:
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);
}
Jetzt bekomme ich eine classcastexception-Fehler in der nächsten Aktivität (Liste auf ein Element klicken).Nichts wurde verändert, in dem die nächste Aktivität;es funktioniert, wenn mit einem SimpleListAdapter für die Liste der Einträge, die (nach dem Klick führen würde, zu Activity2), so dass ich denke, es ist immer noch etwas, was ich falsch mache, in dieser erweiterten Klasse.
Lösung
Es ist nicht wahr, dass convertView wird immer sein, eine vorhandene Instanz;Sie sollten überprüfen, ob es null ist, und dann instanziieren.Wenn nicht, können Sie es ändern, so wie Sie es getan haben.
Dies sollte sein wie:
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);
}
Andere Tipps
Ich würde ändern Sie die getView-Methode:
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;
}
Ich denke, dass Sie immer NPE, weil Sie versuchen, erstellen eine textview und eine Bildansicht in einer Ansicht, wo Sie nicht vorhanden sind.
Wenn Sie möchten, aufblasen ListView mit Einträgen aus einer Datenbank, in Ihrer Tätigkeit, die Sie definieren main.xml mit einer 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>
und in der onCreate-Methode, setzen Sie die Ansicht auf dieses xml mit setContentView(R.layout.main);
.Dann erstellen Sie einen cursor zu Ihrer Datenbank und Ihren benutzerdefinierten adapter:
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);
und Sie definieren eine entry.xml mit Ihrem listIcon und listText, wo der adapter Punkte.In meinem Beispiel, ich bin das Abfragen, die Namen und Telefonnummern aus der Kontaktliste.
In Ihrem benutzerdefinierten adapter haben, sollten Sie Zugriff auf Ihre textview und Bildansicht innerhalb getView oder bindView, ohne jedes problem.
Hier Sie haben und Beispiel, um alle Kontakte in Ihre Kontaktieren Liste mit Bild, name und Nummer, aber mit ListActivity anstelle von Aktivität, und nur eine xml mit zwei Textansicht und eine Bildansicht.Wenn Sie ListActivity, die Sie nicht brauchen, um verwenden Sie eine ListView und Sie nicht benötigen, um die Inhalte anzeigen, die in der Aktivität.
Ich hoffe, es hilft!
Vergessen Sie nicht, setzen :layout_width und layout_heigth für jede der Ansichten .