使用BaseAdapter和ViewHolder的空指针异常

时间:2018-12-27 21:37:57

标签: android view nullpointerexception baseadapter android-viewholder

我在此行得到一个NullPointerException:

viewHolder.list_item_TextView = convertView.findViewById(R.id.listItem_TextView);

如果未实现viewholder,则同一应用程序正在运行,没有任何问题。我添加了viewHolder,就像之前在其他应用中所做的一样,它们正在运行。找不到错误。

public class lv_cb_db_ea_Adapter extends BaseAdapter {

final private Context context;
private Cursor cursor;
private SQLiteDatabase database;


lv_cb_db_ea_Adapter(Context context, Cursor cursor, SQLiteDatabase database) {
    super();
    this.context = context;
    this.cursor = cursor;
    this.database = database;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {

    ViewHolder viewHolder;

    if (convertView == null) {

        LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = layoutInflater.inflate(R.layout.list_item, parent, false);

        viewHolder = (ViewHolder) convertView.getTag();

// ########  here comes the NPE  #########
        viewHolder.list_item_TextView = convertView.findViewById(R.id.listItem_TextView);
        viewHolder.list_item_Checkbox = convertView.findViewById(R.id.listItem_CheckBox);

    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    cursor.moveToPosition(position);

    viewHolder.list_item_TextView.setText("Some Text");
    viewHolder.list_item_Checkbox.setChecked(cursor.getInt(cursor.getColumnIndex("selected")) != 0);

    return convertView;
}

public int getCount() {
    return cursor.getCount();
}

public Object getItem(int position) {
    return position;
}

public long getItemId(int position) {
    return position;
}

private static class ViewHolder {
    CheckBox list_item_Checkbox;
    TextView list_item_TextView;
}
}

这是xml文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">

<CheckBox
    android:id="@+id/listItem_CheckBox"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:focusable="false"
    android:focusableInTouchMode="false" />

<TextView
    android:id="@+id/listItem_TextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toRightOf="@+id/listItem_CheckBox" />

</RelativeLayout>

这是logcat:

java.lang.NullPointerException: Attempt to write to field 'android.widget.TextView ws.rtin.android.listviewexample.lv_cb_db_ea_Adapter$ViewHolder.list_item_TextView' on a null object reference

---添加了database.java和listview.java ----

因为有一些答案(感谢),但不能解决问题,所以我发布了整个应用程序(只有三个小的Java文件和xml)。 “ lv_cb_db_ea”是清单中的主文件。

这是我的数据库。java

public class database extends SQLiteOpenHelper {

database(Context context) {
    super(context, "database", null, 1);
}

@Override
public void onCreate(SQLiteDatabase db) {

    db.execSQL("CREATE TABLE country(" +
            "_id integer primary key autoincrement, " +
            "code varchar(3) not null," +
            "name varchar(30) not null," +
            "selected integer not null)"
    );

    db.execSQL("INSERT INTO country VALUES('0','DK','Dänemark',0)");
    db.execSQL("INSERT INTO country VALUES('1','F','Frankreich',1)");
    db.execSQL("INSERT INTO country VALUES('2','B','Belgien',0)");
    db.execSQL("INSERT INTO country VALUES('3','NL','Niederlande',1)");
    db.execSQL("INSERT INTO country VALUES('4','D','Deutschland',0)");
    db.execSQL("INSERT INTO country VALUES('6','TR','Türkei',0)");
    db.execSQL("INSERT INTO country VALUES('8','S','Schweden',0)");
    db.execSQL("INSERT INTO country VALUES('10','FN','Finnland',0)");
    db.execSQL("INSERT INTO country VALUES('11','GR','Griechenland',0)");
    db.execSQL("INSERT INTO country VALUES('12','A','Östereich',0)");
    db.execSQL("INSERT INTO country VALUES('13','LIT','Litauen',0)");
    db.execSQL("INSERT INTO country VALUES('14','PL','Polen',0)");
    db.execSQL("INSERT INTO country VALUES('15','P','Portugal',0)");
    db.execSQL("INSERT INTO country VALUES('16','I','Italien',0)");
    db.execSQL("INSERT INTO country VALUES('17','GB','Groß Britannien',0)");
    db.execSQL("INSERT INTO country VALUES('18','IRL','Irland',0)");
    db.execSQL("INSERT INTO country VALUES('19','L','Luxemburg',0)");
    db.execSQL("INSERT INTO country VALUES('20','E','Spanien',0)");
    db.execSQL("INSERT INTO country VALUES('21','CH','Schweiz',0)");
    db.execSQL("INSERT INTO country VALUES('22','CZ','Tschechien',0)");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}

这是listView(“ MainActivity”)

public class lv_cb_db_ea extends Activity {

private static SQLiteDatabase sqLiteDatabase;
private Cursor cursor;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // connect to database
    SQLiteOpenHelper database = new database(this);
    sqLiteDatabase = database.getWritableDatabase();
    cursor = getDBContent();

    //create an ArrayAdapter by given database-cursor
    lv_cb_db_ea_Adapter itemAdapter = new lv_cb_db_ea_Adapter(this, cursor, sqLiteDatabase);
    ListView listView = findViewById(R.id.main_ListView);
    listView.setAdapter(itemAdapter);

    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            String sToast = ((TextView) view.findViewById(R.id.listItem_TextView)).getText().toString();
            Toast.makeText(lv_cb_db_ea.this,
                    "Clicked on Row: " + sToast,
                    Toast.LENGTH_SHORT).show();
        }
    });
}

public void findSelected(View v) {
    StringBuilder sToast = new StringBuilder();
    sToast.append("You've selected...\n");
    cursor = sqLiteDatabase.rawQuery("SELECT * FROM country WHERE selected", null);
    while (cursor.moveToNext()) {
        sToast.append("\n").append(cursor.getString(cursor.getColumnIndex("name")));
    }
    Toast.makeText(getApplicationContext(), sToast, Toast.LENGTH_LONG).show();
    cursor.close();
}

// outsourcing query (for more complex queries (i.e. multiple tables))
public static Cursor getDBContent(){
    return sqLiteDatabase.rawQuery("SELECT * FROM country", null);
}

2 个答案:

答案 0 :(得分:1)

该错误告诉您变量viewHolder为空。看一下这段代码:

LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_item, parent, false);

viewHolder = (ViewHolder) convertView.getTag();

问题在于视图的“标签”是保存自定义数据的地方。如果您调用setTag(),它将只有一个值。由于您只是夸大了新版式,因此getTag()会返回null,因为您尚未设置它。相反,您需要创建一个新的ViewHolder并将其设置为视图的标签:

LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_item, parent, false);
viewHolder = new ViewHolder();
convertView.setTag(viewHolder);

答案 1 :(得分:0)

Traceback (most recent call last): File "<stdin>", line 13, in <module> File "<stdin>", line 3, in inf_train_gen NameError: name 'train_gen' is not defined

应该是

viewHolder = (ViewHolder) convertView.getTag();

在if部分。