android中列表视图较大时选择列表项时发生错误?

时间:2018-08-21 18:06:48

标签: java android

当前,我正在Android中制作一个待办事项列表应用程序,它具有编辑文本,按钮和列表视图,单击按钮将文本添加到列表视图时,一切正常,但是当我向其中添加太多项目时列表视图并尝试选择一个列表项,我的应用程序停止运行,并且出现错误提示 java.lang.NullPointerException: Attempt to invoke virtual method 'android.view.View android.view.View.findViewById(int)' on a null object reference 有人知道解决方法吗? 这是我的视图数据方法,它在listview中显示项目

public void viewdata(String tablename)
{
    db = new mydbhandler(this);
    lvitemslist = findViewById(R.id.lvitemlist);
    ArrayList mylist = new ArrayList();
    Cursor c = db.getdata(tablename);
    while(c.moveToNext())
    {
        mylist.add(c.getString(1));
    }
    ListAdapter mylistadapter = new ArrayAdapter(this,R.layout.custom_item_row,R.id.ctv,mylist);
    lvitemslist.setAdapter(mylistadapter);


}

这是onitemclicklistener

lvitemslist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            View v = lvitemslist.getChildAt(i);
            CheckedTextView ctv = v.findViewById(R.id.ctv);

                ctv.setCheckMarkDrawable(android.R.drawable.checkbox_on_background);

db.deletedata(tablename,ctv.getText()。toString());

viewdata(tablename);

1 个答案:

答案 0 :(得分:0)

在您的OnItemClickListener中查看以下行:

View v = lvitemslist.getChildAt(i);

我猜您想将被单击的ListView行分配给变量 v 。但是ViewGroup方法getChildAt(int)ListViewViewGroup的一种)会给您

  

位于指定位置的视图;如果该位置在组中不存在,则为null

(引用自ViewGroup documentation

就像您说的那样,这适用于前几个项目,但对于较高的位置,应用程序崩溃了。这是因为ListView拥有固定数量的子View:同时与子屏幕上的子屏幕数量一样多,另外还有一些子元素可以平滑滚动。对于超出该固定数字的每一行,lvitemslist.getChildAt(i)将返回null

您该怎么做才能修改代码?

幸运的是,您无需做很多工作来获得被点击的View,它作为onItemClick()的参数之一交给您:第二个参数是被点击的ListView行。

所以你只需要写

lvitemslist.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> adapterView, View view, int position, long rowId) {
        CheckedTextView ctv = view.findViewById(R.id.ctv);
        ctv.setCheckMarkDrawable(android.R.drawable.checkbox_on_background);
        db.deletedata(tablename,ctv.getText().toString());
        viewdata(tablename);
    }
}

这将帮助您避免使用NullPointerException

另一件事:通过调用从适配器外部更改ListView行的外观

ctv.setCheckMarkDrawable(android.R.drawable.checkbox_on_background);

这很危险(此网站上有很多问题,导致人们在滚动时会有奇怪的行为)。对于您来说,这可能不是问题,因为您很快便刷新了整个ListView。但是通常应该向适配器提供所有必要的数据,以决定每一行的外观。然后可以更改数据列表,然后当然可以在适配器上调用notifyDatasetChanged()