You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android问题:使用SearchView后ListView删除项不更新求助

问题:SearchView过滤后删除ListView项无法更新

我是Android Studio新手,遇到一个问题:使用SearchView对ListView进行过滤后,删除列表中的项时,ListView无法更新。虽然弹出了删除成功的Toast提示,但被删除的项仍然显示在列表中。

问题截图

  • 应用界面截图:应用界面截图
  • 过滤功能正常显示Lemon的截图:过滤功能正常显示Lemon的截图
  • 使用SearchView后删除Lemon项仍存在的截图:使用SearchView后删除Lemon项仍存在的截图

当前代码

MainActivity.java

public class MainActivity extends AppCompatActivity
{
    EditText item, price;

    Button add;

    ListView listView;
    SearchView searchBox;
    ArrayList<String> itemList = new ArrayList<>();
    ArrayList<String> searchList = new ArrayList<>();
    ArrayAdapter<String> arrayAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        item = findViewById(R.id.edtProdName);
        price = findViewById(R.id.edtPrice);
        add = findViewById(R.id.btnAdd);
        listView = findViewById(R.id.list);
        searchBox = findViewById(R.id.searchView);

        itemList = FileHelper.readData(this);
        arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, android.R.id.text1, itemList);

        listView.setAdapter(arrayAdapter);
        add.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                String prodName = item.getText().toString();
                String prodPrice = price.getText().toString();
                String product = prodName.toUpperCase() +  " " + "P" +  prodPrice.toUpperCase();
                itemList.add(product);
                item.setText("");
                price.setText("");
                FileHelper.writeData(itemList,getApplicationContext());
                arrayAdapter.notifyDataSetChanged();
                Collections.sort(itemList);
            }
        });

        listView.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            {
                AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
                alert.setTitle("Delete");
                alert.setMessage("Do you want to delete this product from the list?");
                alert.setCancelable(false);
                alert.setNegativeButton("No", new DialogInterface.OnClickListener()
                {
                    @Override
                    public void onClick(DialogInterface dialog, int which)
                    {
                        dialog.cancel();
                    }
                });

                alert.setPositiveButton("Yes", new DialogInterface.OnClickListener()
                {
                    @Override
                    public void onClick(DialogInterface dialog, int which)
                    {
                        itemList.remove(position);
                        FileHelper.writeData(itemList, getApplicationContext());
                        arrayAdapter.notifyDataSetChanged();
                        Toast.makeText(MainActivity.this, "Deleted successfully", Toast.LENGTH_SHORT).show();
                    }
                });

                AlertDialog alertDialog = alert.create();
                alertDialog.show();
            }
        });

        searchBox.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText)
            {
                arrayAdapter.getFilter().filter(newText);
                return false;
            }

        });
    }
}

FileHelper.java(用于在设备内存中保存数据)

public class FileHelper
{
    public static final String FILENAME = "listinfo.dat";

    public static void writeData(ArrayList<String> item, Context context)
    {
        try
        {
            FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
            ObjectOutputStream oas = new ObjectOutputStream(fos);
            oas.writeObject(item);
            oas.close();
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }

    }

    public static ArrayList<String> readData(Context context)
    {
        ArrayList<String> itemList = null;
        try
        {
            FileInputStream fis = context.openFileInput(FILENAME);
            ObjectInputStream ois = new ObjectInputStream(fis);
            itemList = (ArrayList<String>) ois.readObject();
        }
        catch (FileNotFoundException e)
        {
            itemList = new ArrayList<>();
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        return itemList;
    }
}

问题原因

当使用arrayAdapter.getFilter().filter(newText)过滤列表时,ArrayAdapter内部会生成一个过滤后的子集,此时ListView展示的是这个子集数据。点击事件返回的position是子集的索引,而非原始itemList的索引。直接用这个position删除itemList元素,要么删错对象,要么删除后未同步更新过滤后的视图,导致被删项依然显示。

解决方案

修改删除逻辑:先获取过滤后列表中被点击的具体项,再从原始列表移除该项,最后重新触发过滤更新视图。

替换AlertDialog中PositiveButton的点击事件代码:

alert.setPositiveButton("Yes", new DialogInterface.OnClickListener()
{
    @Override
    public void onClick(DialogInterface dialog, int which)
    {
        // 获取过滤后列表中被点击的项
        String selectedItem = arrayAdapter.getItem(position);
        // 从原始列表中移除该项
        itemList.remove(selectedItem);
        // 保存更新后的列表
        FileHelper.writeData(itemList, getApplicationContext());
        
        // 根据当前搜索状态更新视图
        String currentQuery = searchBox.getQuery().toString();
        if (!currentQuery.isEmpty()) {
            // 处于过滤状态时,重新触发过滤
            arrayAdapter.getFilter().filter(currentQuery);
        } else {
            // 未过滤时直接刷新适配器
            arrayAdapter.notifyDataSetChanged();
        }
        
        Toast.makeText(MainActivity.this, "Deleted successfully", Toast.LENGTH_SHORT).show();
    }
});

额外说明

  • 这种方式确保删除的是实际点击的项,而非原始列表中对应索引的项。
  • 重新触发过滤能保证搜索状态下,视图同步更新为删除后的过滤结果。

内容的提问来源于stack exchange,提问作者cyla1234

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 19:32:06