首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用BaseAdapter和ViewHolder时出现空指针异常

使用BaseAdapter和ViewHolder时出现空指针异常
EN

Stack Overflow用户
提问于 2018-12-28 05:37:57
回答 2查看 80关注 0票数 0

我在代码行中得到了一个NullPointerException:

代码语言:javascript
复制
viewHolder.list_item_TextView = convertView.findViewById(R.id.listItem_TextView);

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

代码语言:javascript
复制
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文件

代码语言:javascript
复制
<?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:

代码语言:javascript
复制
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“是清单中的主文件。

这是我的database.java

代码语言:javascript
复制
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")

代码语言:javascript
复制
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);
}
EN

回答 2

Stack Overflow用户

发布于 2018-12-28 05:44:53

该错误告诉您变量viewHolder为null。看看这部分代码:

代码语言:javascript
复制
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并将其设置为视图的标记:

代码语言:javascript
复制
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
EN

Stack Overflow用户

发布于 2018-12-28 08:33:34

viewHolder = (ViewHolder) convertView.getTag();

应该是

代码语言:javascript
复制
viewHolder = new ViewHolder();

在if部分。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53951123

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档